junit-team/junit5 · error · JUnitException

Failed to find constructor for

Error message

Failed to find constructor for %s [%s]. Please ensure that a no-argument or a single constructor exists.

What it means

Thrown by ParameterizedTestSpiInstantiator.findBestConstructor() when attempting to instantiate an SPI implementation class (such as a custom ArgumentsProvider, ArgumentConverter, ArgumentsAggregator, or ArgumentsSource) that has multiple declared constructors and none of them is a no-argument constructor. The instantiator first checks for a single constructor (returns it regardless of arity), then looks for a no-arg constructor among multiple, and if neither exists, throws this. The %s placeholders are filled with the SPI interface simple name and the implementation class fully-qualified name.

Solutions

  1. Add a public no-argument constructor to the SPI implementation class
  2. Reduce to a single constructor (any arity) — the instantiator will use it if it's the only one
  3. If the class needs configuration, use annotation-based configuration (implement AnnotationConsumer) rather than constructor parameters
  4. Ensure the class is a top-level class or a static nested class, not a non-static inner class

Example fix

// before — multiple constructors, no no-arg
public class MyArgumentsProvider implements ArgumentsProvider {
    public MyArgumentsProvider(String config) { ... }
    public MyArgumentsProvider(int count) { ... }
}

// after — add a no-arg constructor
public class MyArgumentsProvider implements ArgumentsProvider {
    public MyArgumentsProvider() { }
    public MyArgumentsProvider(String config) { ... }
}

// OR — single constructor (no-arg)
public class MyArgumentsProvider implements ArgumentsProvider {
    public MyArgumentsProvider() { }
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate that an SPI implementation class has a usable constructor before passing it to JUnit
import java.lang.reflect.Constructor;

static <T> boolean hasValidSpiConstructor(Class<? extends T> implClass) {
    Constructor<?>[] ctors = implClass.getDeclaredConstructors();
    if (ctors.length == 1) return true;
    for (Constructor<?> c : ctors) {
        if (c.getParameterCount() == 0) return true;
    }
    return false;
}

// Usage:
if (!hasValidSpiConstructor(MyArgumentsProvider.class)) {
    throw new IllegalStateException(
        MyArgumentsProvider.class.getName() + " must have a no-arg or single constructor");
}

Prevention

When it happens

Trigger: Implement ArgumentsProvider (or any parameterized test SPI) as a class with multiple constructors where none has zero parameters. For example, a custom ArgumentsProvider with both a constructor taking a String and one taking an int, but no default constructor. The instantiator is called when JUnit processes @ArgumentsSource(MyProvider.class) or similar annotations.

Common situations: Custom ArgumentsProvider or ArgumentConverter classes that evolved to have multiple constructors for different initialization modes. Inner classes mistakenly declared as non-static inner classes (which implicitly get a constructor with the outer-class parameter — but this is caught earlier by the isInnerClass check). Classes that use dependency injection frameworks and have constructors with injected parameters.

Related errors


AI-assisted analysis of junit-team/junit5@f070c699a0 (2026-08-11). Data as JSON: /api/errors/ff0470155cc8b298. Report an issue: GitHub.

Appendix: source

Thrown at junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedTestSpiInstantiator.java:72

		Constructor<?>[] constructors = implementationClass.getDeclaredConstructors();

		// Single constructor?
		if (constructors.length == 1) {
			return constructors[0];
		}
		// Find default constructor.
		for (Constructor<?> constructor : constructors) {
			if (constructor.getParameterCount() == 0) {
				return constructor;
			}
		}
		// Otherwise...
		String message = """
				Failed to find constructor for %s [%s]. \
				Please ensure that a no-argument or a single constructor exists.""".formatted(
			spiInterface.getSimpleName(), implementationClass.getName());
		throw new JUnitException(message);
	}

	private ParameterizedTestSpiInstantiator() {
	}

}

View on GitHub (pinned to f070c699a0)