Repository: junit-team/junit-framework (2025-08-08T08:36:45Z)

Issue:
Extend fallback conversion to support `CharSequence` factory arguments
The "[Fallback String-to-Object Conversion](https://docs.junit.org/current/user-guide/#writing-tests-parameterized-tests-argument-conversion-implicit-fallback)" in the parameterized tests only supports `String` as argument.
It would be nice to have `CharSequence` as well to ease these kind of use cases: 

```java
class MyClass {
  public static MyClass parse(CharSequence text) { ... }
}
``` 


Discussion:
Current work on this can be viewed in the following feature branch.

https://github.com/junit-team/junit-framework/compare/main...sbrannen:junit-framework:issues/4815-CharSequence-support-in-fallback-conversion
FYI: I've opened PR #4819 for discussion and review.



Patch:
diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC1.adoc
index 1b3a5f0a8fd7..3d53298ff989 100644
--- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC1.adoc
+++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC1.adoc
@@ -27,6 +27,10 @@ repository on GitHub.
 ==== New Features and Improvements
 
 * Prune stack traces up to test or lifecycle method
+* Convention-based conversion in `ConversionSupport` now supports factory methods and
+  factory constructors that accept a single `CharSequence` argument in addition to the
+  existing support for factories that accept a single `String` argument.
+
 
 [[release-notes-6.0.0-RC1-junit-jupiter]]
 === JUnit Jupiter
@@ -52,6 +56,10 @@ repository on GitHub.
   In addition, special characters are escaped within quoted text. Please refer to the
   <<../user-guide/index.adoc#writing-tests-parameterized-tests-display-names-quoted-text,
   User Guide>> for details.
+* <<../user-guide/index.adoc#writing-tests-parameterized-tests-argument-conversion-implicit-fallback,
+  Fallback String-to-Object Conversion>> for parameterized tests now supports factory
+  methods and factory constructors that accept a single `CharSequence` argument in
+  addition to the existing support for factories that accept a single `String` argument.
 
 
 [[release-notes-6.0.0-RC1-junit-vintage]]
diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/ConversionSupport.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/ConversionSupport.java
index 34ed6ef458f4..ade3e248ca67 100644
--- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/ConversionSupport.java
+++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/ConversionSupport.java
@@ -75,15 +75,20 @@ private ConversionSupport() {
 	 *
 	 * <ol>
 	 * <li>Search for a single, non-private static factory method in the target
-	 * type that converts from a String to the target type. Use the factory method
-	 * if present.</li>
+	 * type that converts from a {@link String} to the target type. Use the
+	 * factory method if present.</li>
 	 * <li>Search for a single, non-private constructor in the target type that
-	 * accepts a String. Use the constructor if present.</li>
+	 * accepts a {@link String}. Use the constructor if present.</li>
+	 * <li>Search for a single, non-private static factory method in the target
+	 * type that converts from a {@link CharSequence} to the target type. Use the
+	 * factory method if present.</li>
+	 * <li>Search for a single, non-private constructor in the target type that
+	 * accepts a {@link CharSequence}. Use the constructor if present.</li>
 	 * </ol>
 	 *
-	 * <p>If multiple suitable factory methods are discovered they will be ignored.
-	 * If neither a single factory method nor a single constructor is found, the
-	 * convention-based conversion strategy will not apply.
+	 * <p>If multiple suitable factory methods or constructors are discovered they
+	 * will be ignored. If neither a single factory method nor a single constructor
+	 * is found, the convention-based conversion strategy will not apply.
 	 *
 	 * @param source the source {@code String} to convert; may be {@code null}
 	 * but only if the target type is a reference type
diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/FallbackStringToObjectConverter.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/FallbackStringToObjectConverter.java
index 916406e3fbcb..80be72128211 100644
--- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/FallbackStringToObjectConverter.java
+++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/FallbackStringToObjectConverter.java
@@ -38,16 +38,21 @@
  * <h2>Search Algorithm</h2>
  *
  * <ol>
- * <li>Search for a single, non-private static factory method in the target
- * type that converts from a String to the target type. Use the factory method
+ * <li>Search for a single, non-private static factory method in the target type
+ * that converts from a {@link String} to the target type. Use the factory method
  * if present.</li>
- * <li>Search for a single, non-private constructor in the target type that
- * accepts a String. Use the constructor if present.</li>
+ * <li>Search for a single, non-private constructor in the target type that accepts
+ * a {@link String}. Use the constructor if present.</li>
+ * <li>Search for a single, non-private static factory method in the target type
+ * that converts from a {@link CharSequence} to the target type. Use the factory
+ * method if present.</li>
+ * <li>Search for a single, non-private constructor in the target type that accepts
+ * a {@link CharSequence}. Use the constructor if present.</li>
  * </ol>
  *
- * <p>If multiple suitable factory methods are discovered they will be ignored.
- * If neither a single factory method nor a single constructor is found, this
- * converter acts as a no-op.
+ * <p>If multiple suitable factory methods or constructors are discovered they
+ * will be ignored. If neither a single factory method nor a single constructor
+ * is found, this converter acts as a no-op.
  *
  * @since 1.11
  * @see ConversionSupport
@@ -86,28 +91,47 @@ public boolean canConvertTo(Class<?> targetType) {
 
 	private static Function<String, @Nullable Object> findFactoryExecutable(Class<?> targetType) {
 		return factoryExecutableCache.computeIfAbsent(targetType, type -> {
-			Method factoryMethod = findFactoryMethod(type);
-			if (factoryMethod != null) {
-				return source -> invokeMethod(factoryMethod, null, source);
+			// First, search for exact String argument matches.
+			Function<String, @Nullable Object> factory = findFactoryExecutable(type, String.class);
+			if (factory != null) {
+				return factory;
 			}
-			Constructor<?> constructor = findFactoryConstructor(type);
-			if (constructor != null) {
-				return source -> newInstance(constructor, source);
+			// Second, fall back to CharSequence argument matches.
+			factory = findFactoryExecutable(type, CharSequence.class);
+			if (factory != null) {
+				return factory;
 			}
+			// Else, nothing found.
 			return NULL_EXECUTABLE;
 		});
 	}
 
-	private static @Nullable Method findFactoryMethod(Class<?> targetType) {
-		List<Method> factoryMethods = findMethods(targetType, new IsFactoryMethod(targetType), BOTTOM_UP);
+	private static @Nullable Function<String, @Nullable Object> findFactoryExecutable(Class<?> targetType,
+			Class<?> parameterType) {
+
+		Method factoryMethod = findFactoryMethod(targetType, parameterType);
+		if (factoryMethod != null) {
+			return source -> invokeMethod(factoryMethod, null, source);
+		}
+		Constructor<?> constructor = findFactoryConstructor(targetType, parameterType);
+		if (constructor != null) {
+			return source -> newInstance(constructor, source);
+		}
+		return null;
+	}
+
+	private static @Nullable Method findFactoryMethod(Class<?> targetType, Class<?> parameterType) {
+		List<Method> factoryMethods = findMethods(targetType, new IsFactoryMethod(targetType, parameterType),
+			BOTTOM_UP);
 		if (factoryMethods.size() == 1) {
 			return factoryMethods.get(0);
 		}
 		return null;
 	}
 
-	private static @Nullable Constructor<?> findFactoryConstructor(Class<?> targetType) {
-		List<Constructor<?>> constructors = findConstructors(targetType, new IsFactoryConstructor(targetType));
+	private static @Nullable Constructor<?> findFactoryConstructor(Class<?> targetType, Class<?> parameterType) {
+		List<Constructor<?>> constructors = findConstructors(targetType,
+			new IsFactoryConstructor(targetType, parameterType));
 		if (constructors.size() == 1) {
 			return constructors.get(0);
 		}
@@ -117,15 +141,9 @@ public boolean canConvertTo(Class<?> targetType) {
 	/**
 	 * {@link Predicate} that determines if the {@link Method} supplied to
 	 * {@link #test(Method)} is a non-private static factory method for the
-	 * supplied {@link #targetType}.
+	 * supplied {@link #targetType} and {@link #parameterType}.
 	 */
-	static class IsFactoryMethod implements Predicate<Method> {
-
-		private final Class<?> targetType;
-
-		IsFactoryMethod(Class<?> targetType) {
-			this.targetType = targetType;
-		}
+	record IsFactoryMethod(Class<?> targetType, Class<?> parameterType) implements Predicate<Method> {
 
 		@Override
 		public boolean test(Method method) {
@@ -136,23 +154,16 @@ public boolean test(Method method) {
 			if (isNotStatic(method)) {
 				return false;
 			}
-			return isNotPrivateAndAcceptsSingleStringArgument(method);
+			return isFactoryCandidate(method, this.parameterType);
 		}
-
 	}
 
 	/**
 	 * {@link Predicate} that determines if the {@link Constructor} supplied to
 	 * {@link #test(Constructor)} is a non-private factory constructor for the
-	 * supplied {@link #targetType}.
+	 * supplied {@link #targetType} and {@link #parameterType}.
 	 */
-	static class IsFactoryConstructor implements Predicate<Constructor<?>> {
-
-		private final Class<?> targetType;
-
-		IsFactoryConstructor(Class<?> targetType) {
-			this.targetType = targetType;
-		}
+	record IsFactoryConstructor(Class<?> targetType, Class<?> parameterType) implements Predicate<Constructor<?>> {
 
 		@Override
 		public boolean test(Constructor<?> constructor) {
@@ -160,15 +171,18 @@ public boolean test(Constructor<?> constructor) {
 			if (!constructor.getDeclaringClass().equals(this.targetType)) {
 				return false;
 			}
-			return isNotPrivateAndAcceptsSingleStringArgument(constructor);
+			return isFactoryCandidate(constructor, this.parameterType);
 		}
-
 	}
 
-	private static boolean isNotPrivateAndAcceptsSingleStringArgument(Executable executable) {
+	/**
+	 * Determine if the supplied {@link Executable} is not private and accepts a
+	 * single argument of the supplied parameter type.
+	 */
+	private static boolean isFactoryCandidate(Executable executable, Class<?> parameterType) {
 		return isNotPrivate(executable) //
 				&& (executable.getParameterCount() == 1) //
-				&& (executable.getParameterTypes()[0] == String.class);
+				&& (executable.getParameterTypes()[0] == parameterType);
 	}
 
 }


Test patch:
diff --git a/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc b/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc
index d0d514e7678e..6252c77d010b 100644
--- a/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc
+++ b/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc
@@ -2519,11 +2519,12 @@ table, JUnit Jupiter also provides a fallback mechanism for automatic conversion
 method_ or a _factory constructor_ as defined below.
 
 - __factory method__: a non-private, `static` method declared in the target type that
-  accepts a single `String` argument and returns an instance of the target type. The name
-  of the method can be arbitrary and need not follow any particular convention.
+  accepts either a single `String` argument or a single `CharSequence` argument and
+  returns an instance of the target type. The name of the method can be arbitrary and need
+  not follow any particular convention.
 - __factory constructor__: a non-private constructor in the target type that accepts a
-  single `String` argument. Note that the target type must be declared as either a
-  top-level class or as a `static` nested class.
+  either a single `String` argument or a single `CharSequence` argument. Note that the
+  target type must be declared as either a top-level class or as a `static` nested class.
 
 NOTE: If multiple _factory methods_ are discovered, they will be ignored. If a _factory
 method_ and a _factory constructor_ are discovered, the factory method will be used
diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestIntegrationTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestIntegrationTests.java
index 6eea54d48e21..cb7fda26c9ff 100644
--- a/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestIntegrationTests.java
+++ b/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestIntegrationTests.java
@@ -311,6 +311,17 @@ void executesWithImplicitGenericConverter() {
 					event(test(), displayName("[2] book = book 2"), finishedWithFailure(message("book 2"))));
 	}
 
+	/**
+	 * @since 6.0
+	 */
+	@Test
+	void executesWithImplicitGenericConverterWithCharSequenceConstructor() {
+		var results = execute("testWithImplicitGenericConverterWithCharSequenceConstructor", Record.class);
+		results.testEvents().assertThatEvents() //
+				.haveExactly(1, event(displayName("\"record 1\""), finishedWithFailure(message("record 1")))) //
+				.haveExactly(1, event(displayName("\"record 2\""), finishedWithFailure(message("record 2"))));
+	}
+
 	@Test
 	void legacyReportingNames() {
 		var results = execute("testWithCustomName", String.class, int.class);
@@ -1460,6 +1471,12 @@ void testWithImplicitGenericConverter(Book book) {
 			fail(book.title);
 		}
 
+		@ParameterizedTest(name = "{0}")
+		@ValueSource(strings = { "record 1", "record 2" })
+		void testWithImplicitGenericConverterWithCharSequenceConstructor(Record record) {
+			fail(record.title.toString());
+		}
+
 		@ParameterizedTest(quoteTextArguments = false)
 		@ValueSource(strings = { "O", "XXX" })
 		void testWithExplicitConverter(@ConvertWith(StringLengthConverter.class) int length) {
@@ -2673,6 +2690,9 @@ static Book factory(String title) {
 		}
 	}
 
+	record Record(CharSequence title) {
+	}
+
 	static class FailureInBeforeEachTestCase {
 
 		@BeforeEach
diff --git a/platform-tests/src/test/java/org/junit/platform/commons/support/conversion/FallbackStringToObjectConverterTests.java b/platform-tests/src/test/java/org/junit/platform/commons/support/conversion/FallbackStringToObjectConverterTests.java
index 5bfc428ec8d7..64b028cb6808 100644
--- a/platform-tests/src/test/java/org/junit/platform/commons/support/conversion/FallbackStringToObjectConverterTests.java
+++ b/platform-tests/src/test/java/org/junit/platform/commons/support/conversion/FallbackStringToObjectConverterTests.java
@@ -12,6 +12,7 @@
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.platform.commons.support.ReflectionSupport.findMethod;
+import static org.junit.platform.commons.util.ReflectionUtils.getDeclaredConstructor;
 
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
@@ -31,13 +32,16 @@
  */
 class FallbackStringToObjectConverterTests {
 
-	private static final IsFactoryMethod isBookFactoryMethod = new IsFactoryMethod(Book.class);
+	private static final IsFactoryMethod isBookFactoryMethod = new IsFactoryMethod(Book.class, String.class);
 
 	private static final FallbackStringToObjectConverter converter = new FallbackStringToObjectConverter();
 
 	@Test
 	void isNotFactoryMethodForWrongParameterType() {
 		assertThat(isBookFactoryMethod).rejects(bookMethod("factory", Object.class));
+		assertThat(isBookFactoryMethod).rejects(bookMethod("factory", Number.class));
+		assertThat(isBookFactoryMethod).rejects(bookMethod("factory", StringBuilder.class));
+		assertThat(new IsFactoryMethod(Record2.class, String.class)).rejects(record2Method("from"));
 	}
 
 	@Test
@@ -52,26 +56,53 @@ void isNotFactoryMethodForNonStaticMethod() {
 
 	@Test
 	void isFactoryMethodForValidMethods() {
-		assertThat(isBookFactoryMethod).accepts(bookMethod("factory"));
-		assertThat(new IsFactoryMethod(Newspaper.class)).accepts(newspaperMethod("from"), newspaperMethod("of"));
-		assertThat(new IsFactoryMethod(Magazine.class)).accepts(magazineMethod("from"), magazineMethod("of"));
+		assertThat(new IsFactoryMethod(Book.class, String.class))//
+				.accepts(bookMethod("factory", String.class));
+		assertThat(new IsFactoryMethod(Book.class, CharSequence.class))//
+				.accepts(bookMethod("factory", CharSequence.class));
+		assertThat(new IsFactoryMethod(Newspaper.class, String.class))//
+				.accepts(newspaperMethod("from"), newspaperMethod("of"));
+		assertThat(new IsFactoryMethod(Magazine.class, String.class))//
+				.accepts(magazineMethod("from"), magazineMethod("of"));
+		assertThat(new IsFactoryMethod(Record2.class, CharSequence.class))//
+				.accepts(record2Method("from"));
 	}
 
 	@Test
 	void isNotFactoryConstructorForPrivateConstructor() {
-		assertThat(new IsFactoryConstructor(Magazine.class)).rejects(constructor(Magazine.class));
+		assertThat(new IsFactoryConstructor(Magazine.class, String.class)).rejects(constructor(Magazine.class));
+	}
+
+	@Test
+	void isNotFactoryConstructorForWrongParameterType() {
+		assertThat(new IsFactoryConstructor(Record1.class, String.class))//
+				.rejects(getDeclaredConstructor(Record1.class));
+		assertThat(new IsFactoryConstructor(Record2.class, String.class))//
+				.rejects(getDeclaredConstructor(Record2.class));
 	}
 
 	@Test
 	void isFactoryConstructorForValidConstructors() {
-		assertThat(new IsFactoryConstructor(Book.class)).accepts(constructor(Book.class));
-		assertThat(new IsFactoryConstructor(Journal.class)).accepts(constructor(Journal.class));
-		assertThat(new IsFactoryConstructor(Newspaper.class)).accepts(constructor(Newspaper.class));
+		assertThat(new IsFactoryConstructor(Book.class, String.class))//
+				.accepts(constructor(Book.class));
+		assertThat(new IsFactoryConstructor(Journal.class, String.class))//
+				.accepts(constructor(Journal.class));
+		assertThat(new IsFactoryConstructor(Newspaper.class, String.class))//
+				.accepts(constructor(Newspaper.class));
+		assertThat(new IsFactoryConstructor(Record1.class, CharSequence.class))//
+				.accepts(getDeclaredConstructor(Record1.class));
+		assertThat(new IsFactoryConstructor(Record2.class, CharSequence.class))//
+				.accepts(getDeclaredConstructor(Record2.class));
 	}
 
 	@Test
 	void convertsStringToBookViaStaticFactoryMethod() throws Exception {
-		assertConverts("enigma", Book.class, Book.factory("enigma"));
+		assertConverts("enigma", Book.class, new Book("factory(String): enigma"));
+	}
+
+	@Test
+	void convertsStringToRecord2ViaStaticFactoryMethodAcceptingCharSequence() throws Exception {
+		assertConvertsRecord2("enigma", Record2.from(new StringBuffer("enigma")));
 	}
 
 	@Test
@@ -79,6 +110,11 @@ void convertsStringToJournalViaFactoryConstructor() throws Exception {
 		assertConverts("enigma", Journal.class, new Journal("enigma"));
 	}
 
+	@Test
+	void convertsStringToRecord1ViaFactoryConstructorAcceptingCharSequence() throws Exception {
+		assertConvertsRecord1("enigma", new Record1(new StringBuffer("enigma")));
+	}
+
 	@Test
 	void convertsStringToNewspaperViaConstructorIgnoringMultipleFactoryMethods() throws Exception {
 		assertConverts("enigma", Newspaper.class, new Newspaper("enigma"));
@@ -119,16 +155,43 @@ private static Method magazineMethod(String methodName) {
 		return findMethod(Magazine.class, methodName, String.class).orElseThrow();
 	}
 
+	private static Method record2Method(String methodName) {
+		return findMethod(Record2.class, methodName, CharSequence.class).orElseThrow();
+	}
+
 	private static void assertConverts(String input, Class<?> targetType, Object expectedOutput) throws Exception {
-		assertThat(converter.canConvertTo(targetType)).isTrue();
+		assertCanConvertTo(targetType);
 
 		var result = converter.convert(input, targetType);
 
 		assertThat(result) //
-				.describedAs(input + " --(" + targetType.getName() + ")--> " + expectedOutput) //
+				.as(input + " (" + targetType.getSimpleName() + ") --> " + expectedOutput) //
 				.isEqualTo(expectedOutput);
 	}
 
+	private static void assertConvertsRecord1(String input, Record1 expected) throws Exception {
+		Class<?> targetType = Record1.class;
+		assertCanConvertTo(targetType);
+
+		Record1 result = (Record1) converter.convert(input, targetType);
+
+		assertThat(result).isNotNull();
+		assertThat(result.title.toString()).isEqualTo(expected.title.toString());
+	}
+
+	private static void assertConvertsRecord2(String input, Record2 expected) throws Exception {
+		Class<?> targetType = Record2.class;
+		assertCanConvertTo(targetType);
+
+		var result = converter.convert(input, targetType);
+
+		assertThat(result).isEqualTo(expected);
+	}
+
+	private static void assertCanConvertTo(Class<?> targetType) {
+		assertThat(converter.canConvertTo(targetType)).as("canConvertTo(%s)", targetType.getSimpleName()).isTrue();
+	}
+
 	static class Book {
 
 		private final String title;
@@ -139,12 +202,35 @@ static class Book {
 
 		// static and non-private
 		static Book factory(String title) {
-			return new Book(title);
+			return new Book("factory(String): " + title);
+		}
+
+		/**
+		 * Static and non-private, but intentionally overloads {@link #factory(String)}
+		 * with a {@link CharSequence} argument to ensure that we don't introduce a
+		 * regression in 6.0, since the String-based factory method should take
+		 * precedence over a CharSequence-based factory method.
+		 */
+		static Book factory(CharSequence title) {
+			return new Book("factory(CharSequence): " + title);
 		}
 
 		// wrong parameter type
 		static Book factory(Object obj) {
-			return new Book(String.valueOf(obj));
+			throw new UnsupportedOperationException();
+		}
+
+		// wrong parameter type
+		static Book factory(Number number) {
+			throw new UnsupportedOperationException();
+		}
+
+		/**
+		 * Wrong parameter type, intentionally a subtype of {@link CharSequence}
+		 * other than {@link String}.
+		 */
+		static Book factory(StringBuilder builder) {
+			throw new UnsupportedOperationException();
 		}
 
 		@SuppressWarnings("unused")
@@ -166,6 +252,10 @@ public int hashCode() {
 			return Objects.hash(title);
 		}
 
+		@Override
+		public String toString() {
+			return "Book [title=" + this.title + "]";
+		}
 	}
 
 	static class Journal {
@@ -176,6 +266,16 @@ static class Journal {
 			this.title = title;
 		}
 
+		/**
+		 * Intentionally overloads {@link #Journal(String)} with a {@link CharSequence}
+		 * argument to ensure that we don't introduce a regression in 6.0, since the
+		 * String-based constructor should take precedence over a CharSequence-based
+		 * constructor.
+		 */
+		Journal(CharSequence title) {
+			this("Journal(CharSequence): " + title);
+		}
+
 		@Override
 		public boolean equals(Object obj) {
 			return (this == obj) || (obj instanceof Journal that && Objects.equals(this.title, that.title));
@@ -186,6 +286,10 @@ public int hashCode() {
 			return Objects.hash(title);
 		}
 
+		@Override
+		public String toString() {
+			return "Journal [title=" + this.title + "]";
+		}
 	}
 
 	static class Newspaper {
@@ -214,6 +318,10 @@ public int hashCode() {
 			return Objects.hash(title);
 		}
 
+		@Override
+		public String toString() {
+			return "Newspaper [title=" + this.title + "]";
+		}
 	}
 
 	static class Magazine {
@@ -231,6 +339,16 @@ static Magazine of(String title) {
 
 	}
 
+	record Record1(CharSequence title) {
+	}
+
+	record Record2(CharSequence title) {
+
+		static Record2 from(CharSequence title) {
+			return new Record2("Record2(CharSequence): " + title);
+		}
+	}
+
 	static class Diary {
 	}