junit-team/junit5 · error · JUnitException

This class must not be instantiated

Error message

This class must not be instantiated

What it means

Thrown as a JUnitException by the private constructor of the inner sentinel class ClassOrderer.Default. The class exists only to be referenced by its Class literal (e.g. @TestClassOrder(ClassOrderer.Default.class)) to signal 'use the configured default orderer'; it is a marker and must never be instantiated. The constructor throws to fail-fast on accidental instantiation.

Source

Thrown at junit-jupiter-api/src/main/java/org/junit/jupiter/api/ClassOrderer.java:123

	 * ordering should be applied.
	 *
	 * <p>If the {@value #DEFAULT_ORDER_PROPERTY_NAME} is set, specifying this
	 * {@code ClassOrderer} has the same effect as referencing the configured
	 * class directly. Otherwise, it has the same effect as not specifying any
	 * {@code ClassOrderer}.
	 *
	 * <p>This class can be used to reset the {@code ClassOrderer} for a
	 * {@link Nested @Nested} class and its {@code @Nested} inner classes,
	 * recursively, when a {@code ClassOrderer} is configured using
	 * {@link TestClassOrder @TestClassOrder} on an enclosing class.
	 *
	 * @since 6.0
	 */
	@API(status = EXPERIMENTAL, since = "6.0")
	final class Default implements ClassOrderer {

		private Default() {
			throw new JUnitException("This class must not be instantiated");
		}

		@Override
		public void orderClasses(ClassOrdererContext context) {
			// never called
		}
	}

	/**
	 * {@code ClassOrderer} that sorts classes alphanumerically based on their
	 * fully qualified names using {@link String#compareTo(String)}.
	 */
	class ClassName implements ClassOrderer {

		public ClassName() {
		}

		/**

View on GitHub (pinned to 956246301e)

Solutions

  1. Reference the class by literal only: use @TestClassOrder(ClassOrderer.Default.class), never new ClassOrderer.Default().
  2. If scanning for ClassOrderer subtypes, exclude sentinel classes whose simple name is 'Default' (or check Modifier.isPrivate(constructor) and skip).
  3. Refactor generic instantiation code to take a no-arg factory / supplier instead of reflectively newInstance-ing arbitrary subclasses.

Example fix

// before
ClassOrderer o = ReflectionSupport.newInstance(ClassOrderer.Default.class);

// after — never instantiate; pass the class literal to the annotation
@TestClassOrder(ClassOrderer.Default.class)
class MyTests {}
Defensive patterns

Strategy: validation

Validate before calling

// Before reflectively instantiating a ClassOrderer, skip sentinels
Class<?> clazz = candidate;
boolean isSentinel = clazz == org.junit.jupiter.api.ClassOrderer.Default.class;
if (isSentinel) {
    return; // never instantiate
}

Type guard

static boolean isInstantiableOrderer(Class<?> c) {
    return ClassOrderer.class.isAssignableFrom(c)
        && c != ClassOrderer.Default.class
        && !Modifier.isAbstract(c.getModifiers());
}

Prevention

When it happens

Trigger: Using reflection to instantiate ClassOrderer.Default via ReflectionSupport.newInstance, Constructor.newInstance, or Class.getDeclaredConstructor().newInstance() (the private constructor is made accessible). Normal @TestClassOrder usage only references the .class literal and never triggers this.

Common situations: Test frameworks or generic factory code that reflectively instantiates any ClassOrderer implementation by scanning the classpath; copy-paste of an instantiation pattern from a real orderer (ClassName, OrderAnnotation) onto the Default marker.

Related errors


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