{"id":"5b60d96fb9073921","repo":"junit-team/junit5","slug":"the-following-testinstancefactory-extensions-were","errorCode":null,"errorMessage":"The following TestInstanceFactory extensions were registered for test class [%s], but only one is permitted: %s","messagePattern":"The following TestInstanceFactory extensions were registered for test class \\[(.+?)\\], but only one is permitted: (.+?)","errorType":"exception","errorClass":"ExtensionConfigurationException","httpStatus":null,"severity":"error","filePath":"junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassBasedTestDescriptor.java","lineNumber":311,"sourceCode":"\t\tthis.testInstanceFactory = null;\n\t}\n\n\tprivate @Nullable TestInstanceFactory resolveTestInstanceFactory(ExtensionRegistry registry) {\n\t\tList<TestInstanceFactory> factories = registry.getExtensions(TestInstanceFactory.class);\n\n\t\tif (factories.size() == 1) {\n\t\t\treturn factories.get(0);\n\t\t}\n\n\t\tif (factories.size() > 1) {\n\t\t\tString factoryNames = factories.stream()//\n\t\t\t\t\t.map(factory -> factory.getClass().getName())//\n\t\t\t\t\t.collect(joining(\", \"));\n\n\t\t\tString errorMessage = \"The following TestInstanceFactory extensions were registered for test class [%s], but only one is permitted: %s\".formatted(\n\t\t\t\tgetTestClass().getName(), factoryNames);\n\n\t\t\tthrow new ExtensionConfigurationException(errorMessage);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tprivate TestInstancesProvider testInstancesProvider(JupiterEngineExecutionContext parentExecutionContext,\n\t\t\tClassExtensionContext ourExtensionContext) {\n\n\t\t// For Lifecycle.PER_CLASS, ourExtensionContext.getTestInstances() is used to store the instance.\n\t\t// Otherwise, extensionContext.getTestInstances() is always empty and we always create a new instance.\n\t\treturn (registry, context) -> ourExtensionContext.getTestInstances().orElseGet(\n\t\t\t() -> instantiateAndPostProcessTestInstance(parentExecutionContext, ourExtensionContext, registry,\n\t\t\t\tcontext));\n\t}\n\n\tprivate TestInstances instantiateAndPostProcessTestInstance(JupiterEngineExecutionContext parentExecutionContext,\n\t\t\tClassExtensionContext ourExtensionContext, ExtensionRegistry registry,\n\t\t\tJupiterEngineExecutionContext context) {","sourceCodeStart":293,"sourceCodeEnd":329,"githubUrl":"https://github.com/junit-team/junit5/blob/956246301e03d757539f7b76dd5a91f298637563/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassBasedTestDescriptor.java#L293-L329","documentation":"Thrown by ClassBasedTestDescriptor.resolveTestInstanceFactory() during the prepare() phase when the registry contains more than one TestInstanceFactory extension for a single test class. JUnit Jupiter permits at most one TestInstanceFactory per class because two factories would produce ambiguous instances, so the engine fails the entire class up front.","triggerScenarios":"Registering two TestInstanceFactory implementations for the same class via any combination of @ExtendWith on the class/meta-annotation, @RegisterExtension static fields, programmatic registration via @ExtendsWith on a base class plus a subclass, or a META-INF/services extension auto-registered globally that also implements TestInstanceFactory alongside a locally registered one.","commonSituations":"Mixing a test-instance-creation framework (e.g. a Mockito/Guice/Spring testinstance factory extension) with a custom factory; upgrading a library that now ships its own TestInstanceFactory that collides with yours; a ServiceLoader-registered extension that auto-applies to all classes while a @RegisterExtension also supplies one.","solutions":["Read the message: it lists the offending factory class names — remove or disable all but one.","If one factory comes from a third-party extension registered via ServiceLoader (META-INF/services/org.junit.jupiter.api.extension.Extension), exclude that class from automatic registration or do not annotate it.","Consolidate instance creation into a single TestInstanceFactory that delegates internally if you need multiple strategies.","Check for @ExtendWith on both a base test class and a subclass pointing at different factory classes."],"exampleFix":"// before — two factories for one class\n@ExtendWith(GuiceTestInstanceFactory.class)\nclass BaseTest {}\n\n@ExtendWith(CustomTestInstanceFactory.class)\nclass ChildTest extends BaseTest {} // both apply -> ExtensionConfigurationException\n\n// after — single factory, composition handled inside\n@ExtendWith(GuiceTestInstanceFactory.class)\nclass BaseTest {}\nclass ChildTest extends BaseTest {}","handlingStrategy":"validation","validationCode":"// At suite setup, count TestInstanceFactory extensions for the class\nList<TestInstanceFactory> factories = new ArrayList<>();\nReflectionUtils.findMethods(...) // or scan @ExtendWith on the class hierarchy\nif (factories.size() > 1) throw new IllegalStateException(\"Duplicate TestInstanceFactory: \" + factories);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep at most one TestInstanceFactory per test class across the whole annotation hierarchy.","Audit META-INF/services extension files for auto-registered factories that could collide.","When adopting a DI test extension that ships a factory, remove any custom one you wrote."],"tags":["junit-jupiter","extension","test-instance-factory","configuration"],"analyzedSha":"956246301e03d757539f7b76dd5a91f298637563","analyzedAt":"2026-08-04T19:25:17.049Z","schemaVersion":2}