junit-team/junit5 · error · UnsupportedOperationException

Implement generateDisplayNameForNestedClass(List<Class<?>>,

Error message

Implement generateDisplayNameForNestedClass(List<Class<?>>, Class<?>) instead

What it means

Thrown as UnsupportedOperationException by the deprecated default method generateDisplayNameForNestedClass(Class<?>) on the DisplayNameGenerator interface. Since 5.12 the new signature is generateDisplayNameForNestedClass(List<Class<?>>, Class<?>); the old method now throws by default to push implementors onto the new signature. The new default delegates to the old one, so a custom generator that overrides neither will hit this when a @Nested test is rendered.

Source

Thrown at junit-jupiter-api/src/main/java/org/junit/jupiter/api/DisplayNameGenerator.java:118

	 * @return the display name for the class; never blank
	 */
	String generateDisplayNameForClass(Class<?> testClass);

	/**
	 * Generate a display name for the given {@link Nested @Nested} inner test
	 * class.
	 *
	 * <p>If this method returns {@code null}, the default display name
	 * generator will be used instead.
	 *
	 * @param nestedClass the class to generate a name for; never {@code null}
	 * @return the display name for the nested class; never blank
	 * @deprecated in favor of {@link #generateDisplayNameForNestedClass(List, Class)}
	 */
	@API(status = DEPRECATED, since = "5.12")
	@Deprecated(since = "5.12")
	default String generateDisplayNameForNestedClass(Class<?> nestedClass) {
		throw new UnsupportedOperationException(
			"Implement generateDisplayNameForNestedClass(List<Class<?>>, Class<?>) instead");
	}

	/**
	 * Generate a display name for the given {@link Nested @Nested} inner test
	 * class.
	 *
	 * <p>If this method returns {@code null}, the default display name
	 * generator will be used instead.
	 *
	 * @implNote The classes supplied as {@code enclosingInstanceTypes} may
	 * differ from the classes returned from invocations of
	 * {@link Class#getEnclosingClass()} &mdash; for example, when a nested test
	 * class is inherited from a superclass.
	 *
	 * @param enclosingInstanceTypes the runtime types of the enclosing
	 * instances for the test class, ordered from outermost to innermost,
	 * excluding {@code nestedClass}; never {@code null}

View on GitHub (pinned to 956246301e)

Solutions

  1. Override the new method in your custom generator: generateDisplayNameForNestedClass(List<Class<?>> enclosingInstanceTypes, Class<?> nestedClass).
  2. If migrating, change the old override's signature to the new one (add the enclosingInstanceTypes parameter) and adapt the body.
  3. Prefer extending a built-in base (DisplayNameGenerator.Standard / Simple / ReplaceUnderscores / IndicativeSentences) which already implement the new signature, instead of implementing the interface from scratch.

Example fix

// before
public class MyGenerator implements DisplayNameGenerator {
    public String generateDisplayNameForNestedClass(Class<?> nestedClass) { // deprecated, no longer called
        return nestedClass.getSimpleName();
    }
}

// after
@Override
public String generateDisplayNameForNestedClass(List<Class<?>> enclosingInstanceTypes, Class<?> nestedClass) {
    return nestedClass.getSimpleName();
}
Defensive patterns

Strategy: type-guard

Validate before calling

// At registration time, check that your generator implements the new nested-class method
Class<? extends DisplayNameGenerator> g = MyGenerator.class;
boolean hasNewNested = Arrays.stream(g.getMethods())
    .anyMatch(m -> m.getName().equals("generateDisplayNameForNestedClass")
        && m.getParameterCount() == 2);
if (!hasNewNested) throw new IllegalStateException(g + " must implement generateDisplayNameForNestedClass(List, Class)");

Type guard

static boolean implementsNewNestedSignature(Class<? extends DisplayNameGenerator> g) {
    try {
        return g.getMethod("generateDisplayNameForNestedClass", java.util.List.class, Class.class)
                .getDeclaringClass() == g;
    } catch (NoSuchMethodException e) { return false; }
}

Prevention

When it happens

Trigger: A custom DisplayNameGenerator implementation (registered globally via junit.jupiter.displayname.generator.default or locally via @DisplayNameGeneration) that does NOT override the new generateDisplayNameForNestedClass(List<Class<?>>, Class<?>) method, when JUnit renders a @Nested test class display name. The new default routes to the old default which throws.

Common situations: Custom DisplayNameGenerator written before 5.12 that overrode the single-arg method, then upgraded; the override no longer matches the new signature and silently falls through to the throwing default. Also a fresh generator where the author only implemented generateDisplayNameForClass and forgot nested classes.

Related errors


AI-assisted analysis of junit-team/junit5@956246301e (2026-08-04). Data as JSON: /data/errors/2d26e2820bdc76c9.json. Report an issue: GitHub.