Close

JUnit 5 - TestInstanceFactory Extension

[Last Updated: Jan 1, 2026]

The TestInstanceFactory interface defines the API for Extensions that wish to create test instances manually. By default, JUnit Jupiter instantiates test classes using their no-args constructor. Implementing this interface allows you to use parameterized constructors or complex factory logic.

Java source and doc

Definition of TestInstanceFactory

Version: 6.0.1
 package org.junit.jupiter.api.extension;
 @FunctionalInterface
 @API(status = STABLE, since = "5.7")
 public interface TestInstanceFactory extends TestInstantiationAwareExtension {
     Object createTestInstance(TestInstanceFactoryContext factoryContext, 1
                               ExtensionContext extensionContext)
                               throws TestInstantiationException;
 }
1Callback for creating a test instance for the supplied context.

Example

In this example, our test class does not have a default constructor. Instead, it requires a unique ID string. The StringConstructorTestInstanceFactory extension handles the reflection logic to find the correct constructor and inject a random UUID.

package com.logicbig.example;

import java.lang.reflect.Constructor;
import java.util.UUID;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.TestInstanceFactory;
import org.junit.jupiter.api.extension.TestInstanceFactoryContext;

public class StringConstructorTestInstanceFactory implements TestInstanceFactory {

    @Override
    public Object createTestInstance(
            TestInstanceFactoryContext factoryContext,
            ExtensionContext extensionContext) {

        Class<?> testClass = factoryContext.getTestClass();
        String id = "TEST-" + UUID.randomUUID();

        try {
            Constructor<?> constructor = testClass.getDeclaredConstructor(String.class);
            constructor.setAccessible(true);
            return constructor.newInstance(id);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(
                    "Test class must declare a constructor with a single String parameter: "
                            + testClass.getName(), e);
        } catch (Exception e) {
            throw new RuntimeException(
                    "Failed to create test instance for: " + testClass.getName(), e);
        }
    }
}

Test Class

package com.logicbig.example;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

@ExtendWith(StringConstructorTestInstanceFactory.class)
public class InstanceFactoryTest {
    private final String testId;

    public InstanceFactoryTest(String testId) {
        this.testId = testId;
    }

    @Test
    void testWithInjectedId() {
        System.out.println("Test Instance ID: " + testId);
    }
}

Output

$ mvn test -Dtest=InstanceFactoryTest
[INFO] Scanning for projects...
[INFO]
[INFO] ---------< com.logicbig.example:junit-5-test-instance-factory >---------
[INFO] Building junit-5-test-instance-factory 1.0-SNAPSHOT
[INFO] from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- resources:3.3.1:resources (default-resources) @ junit-5-test-instance-factory ---
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory D:\example-projects\junit-5\junit-5-extensions\junit-5-test-instance-factory\src\main\resources
[INFO]
[INFO] --- compiler:3.13.0:compile (default-compile) @ junit-5-test-instance-factory ---
[INFO] No sources to compile
[INFO]
[INFO] --- resources:3.3.1:testResources (default-testResources) @ junit-5-test-instance-factory ---
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory D:\example-projects\junit-5\junit-5-extensions\junit-5-test-instance-factory\src\test\resources
[INFO]
[INFO] --- compiler:3.13.0:testCompile (default-testCompile) @ junit-5-test-instance-factory ---
[INFO] Recompiling the module because of changed source code.
[WARNING] File encoding has not been set, using platform encoding windows-1252, i.e. build is platform dependent!
[INFO] Compiling 2 source files with javac [debug target 17] to target\test-classes
[INFO]
[INFO] --- surefire:3.5.0:test (default-test) @ junit-5-test-instance-factory ---
[INFO] Using auto detected provider org.apache.maven.surefire.junitplatform.JUnitPlatformProvider
[INFO]
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
Test Instance ID: TEST-1783d70f-1259-4ab4-8b92-2fd707289feb
[INFO] +--com.logicbig.example.InstanceFactoryTest - 0.168 ss
[INFO] | '-- [OK] testWithInjectedId - 0.050 ss
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4.209 s
[INFO] Finished at: 2025-12-30T17:59:48+08:00
[INFO] ------------------------------------------------------------------------

The successful execution of the test confirms that JUnit successfully utilized our factory to create the test instance. Even though the test class lacked a no-args constructor, the extension provided the necessary String argument during instantiation, as evidenced by the UUID printed in the test output. This demonstrates how TestInstanceFactory provides full control over the instantiation phase of the test lifecycle.

Example Project

Dependencies and Technologies Used:

  • junit-jupiter-engine 6.0.1 (Module "junit-jupiter-engine" of JUnit)
     Version Compatibility: 5.3.0 - 6.0.1Version List
    ×

    Version compatibilities of junit-jupiter-engine with this example:

    • 5.3.0
    • 5.3.1
    • 5.3.2
    • 5.4.0
    • 5.4.1
    • 5.4.2
    • 5.5.0
    • 5.5.1
    • 5.5.2
    • 5.6.0
    • 5.6.1
    • 5.6.2
    • 5.6.3
    • 5.7.0
    • 5.7.1
    • 5.7.2
    • 5.8.0
    • 5.8.1
    • 5.8.2
    • 5.9.0
    • 5.9.1
    • 5.9.2
    • 5.9.3
    • 5.10.0
    • 5.10.1
    • 5.10.2
    • 5.10.3
    • 5.10.4
    • 5.10.5
    • 5.11.0
    • 5.11.1
    • 5.11.2
    • 5.11.3
    • 5.11.4
    • 5.12.0
    • 5.12.1
    • 5.12.2
    • 5.13.0
    • 5.13.1
    • 5.13.2
    • 5.13.3
    • 5.13.4
    • 5.14.0
    • 5.14.1
    • 6.0.0
    • 6.0.1

    Versions in green have been tested.

  • JDK 25
  • Maven 3.9.11

JUnit 5 - TestInstanceFactory Select All Download
  • junit-5-test-instance-factory
    • src
      • test
        • java
          • com
            • logicbig
              • example
                • InstanceFactoryTest.java

    See Also