Bird
Raised Fist0
JUnittesting~8 mins

@ExtendWith annotation in JUnit - Framework Patterns

Choose your learning style10 modes available
Framework Mode - @ExtendWith annotation
Folder Structure
project-root/
├── src/
│   ├── main/
│   │   └── java/
│   │       └── com/example/app/
│   │           └── Application.java
│   └── test/
│       └── java/
│           └── com/example/app/
│               ├── extensions/
│               │   └── CustomExtension.java
│               ├── tests/
│               │   └── SampleTest.java
│               └── utils/
│                   └── TestUtils.java
└── pom.xml

This structure follows Maven conventions for a JUnit test project. The extensions folder holds custom extension classes used with @ExtendWith. Test classes are under tests.

Test Framework Layers
  • Extension Layer: Custom JUnit 5 extensions implementing interfaces like BeforeEachCallback, AfterEachCallback, etc. These are applied with @ExtendWith.
  • Test Layer: Test classes annotated with @Test and @ExtendWith to use extensions.
  • Utility Layer: Helper classes and methods to support tests and extensions.
  • Configuration Layer: Handles environment setup, test parameters, and extension configuration.
Configuration Patterns
  • Extension Registration: Use @ExtendWith(CustomExtension.class) on test classes or methods to register extensions.
  • Environment Properties: Use System.getProperty or @TestPropertySource to pass environment variables to extensions.
  • Parameter Resolution: Extensions can implement ParameterResolver to inject test data or mocks.
  • Profiles: Use Maven profiles or JUnit tags to run tests with different extension configurations.
Test Reporting and CI/CD Integration
  • JUnit 5 produces standard XML reports compatible with CI tools like Jenkins, GitHub Actions, or GitLab CI.
  • Extensions can log additional info or capture screenshots on failure for richer reports.
  • Integrate with build tools (Maven/Gradle) to run tests automatically on code commits.
  • Use CI pipelines to run tests with different extension configurations or environments.
Best Practices
  1. Single Responsibility: Each extension should do one thing, like logging, timing, or resource management.
  2. Reusable Extensions: Design extensions to be reusable across multiple test classes.
  3. Explicit Registration: Use @ExtendWith explicitly on test classes or methods for clarity.
  4. Parameter Injection: Use ParameterResolver to inject dependencies cleanly.
  5. Fail Fast: Extensions should fail tests quickly if preconditions are not met.
Self Check

Where in this folder structure would you add a new extension class that logs test execution time?

Key Result
Use @ExtendWith to register reusable JUnit 5 extensions that add behavior to tests cleanly and modularly.

Practice

(1/5)
1. What is the primary purpose of the @ExtendWith annotation in JUnit 5?
easy
A. To mark a method as a test case
B. To disable a test method temporarily
C. To register extensions that add extra behavior to tests
D. To specify the order of test execution

Solution

  1. Step 1: Understand the role of @ExtendWith

    This annotation is used to register extensions that can add behavior before, after, or around tests.
  2. Step 2: Compare with other annotations

    Other annotations like @Test mark test methods, but @ExtendWith is specifically for extensions.
  3. Final Answer:

    To register extensions that add extra behavior to tests -> Option C
  4. Quick Check:

    @ExtendWith = register extensions [OK]
Hint: Remember: @ExtendWith adds extra test behavior [OK]
Common Mistakes:
  • Confusing @ExtendWith with @Test
  • Thinking it disables tests
  • Assuming it controls test order
2. Which of the following is the correct syntax to use @ExtendWith to register a custom extension named MyExtension.class on a test class?
easy
A. @ExtendWith(MyExtension.class) public class TestClass {}
B. @ExtendWith{MyExtension.class} public class TestClass {}
C. @ExtendWith[MyExtension.class] public class TestClass {}
D. @ExtendWith public class TestClass {}

Solution

  1. Step 1: Recall correct annotation syntax

    Annotations use parentheses with class references, like @ExtendWith(MyExtension.class).
  2. Step 2: Identify invalid syntax

    Curly braces, square brackets, or angle brackets are not valid for this annotation.
  3. Final Answer:

    @ExtendWith(MyExtension.class) public class TestClass {} -> Option A
  4. Quick Check:

    Annotation syntax uses parentheses () [OK]
Hint: Use parentheses () with class name for annotations [OK]
Common Mistakes:
  • Using curly braces {} instead of parentheses
  • Using square brackets [] or angle brackets <>
  • Omitting .class after the class name
3. Given the following code snippet, what will be printed when the test runs?
@ExtendWith(MyExtension.class)
public class SampleTest {
    @Test
    void testMethod() {
        System.out.println("Test running");
    }
}

class MyExtension implements BeforeTestExecutionCallback {
    public void beforeTestExecution(ExtensionContext context) {
        System.out.println("Before test");
    }
}
medium
A. Before test
B. Test running\nBefore test
C. Test running
D. Before test\nTest running

Solution

  1. Step 1: Understand extension behavior

    The MyExtension implements BeforeTestExecutionCallback, so it runs code before the test method.
  2. Step 2: Trace output order

    First, "Before test" prints from the extension, then "Test running" prints from the test method.
  3. Final Answer:

    Before test\nTest running -> Option D
  4. Quick Check:

    Extension beforeTestExecution runs before test method [OK]
Hint: BeforeTestExecutionCallback runs before test method [OK]
Common Mistakes:
  • Assuming extension runs after test
  • Ignoring extension output
  • Confusing output order
4. Identify the error in the following JUnit 5 test class using @ExtendWith:
@ExtendWith
public class FaultyTest {
    @Test
    void testSomething() {}
}
medium
A. @ExtendWith cannot be used on classes
B. @ExtendWith is missing the extension class argument
C. The test method must be static
D. The test method must return a value

Solution

  1. Step 1: Check @ExtendWith usage

    The annotation requires specifying which extension class to use, e.g., @ExtendWith(MyExtension.class).
  2. Step 2: Validate other options

    It is valid on classes, test methods do not need to be static or return values.
  3. Final Answer:

    @ExtendWith is missing the extension class argument -> Option B
  4. Quick Check:

    @ExtendWith needs extension class specified [OK]
Hint: Always specify extension class inside @ExtendWith() [OK]
Common Mistakes:
  • Omitting the extension class argument
  • Thinking @ExtendWith can't be on classes
  • Believing test methods must be static
5. You want to reuse a setup logic that prints "Setup done" before each test method in multiple test classes. How should you apply @ExtendWith to achieve this cleanly?
hard
A. Create a custom extension class implementing BeforeEachCallback and annotate each test class with @ExtendWith(YourExtension.class)
B. Add a static method printing "Setup done" and call it manually in each test method
C. Use @BeforeAll annotation in each test class to print "Setup done"
D. Annotate each test method with @ExtendWith(YourExtension.class) instead of the class

Solution

  1. Step 1: Identify reusable setup approach

    Implementing a custom extension with BeforeEachCallback allows running code before each test method.
  2. Step 2: Apply @ExtendWith on test classes

    Annotating test classes with @ExtendWith(YourExtension.class) reuses the setup logic cleanly across classes.
  3. Step 3: Evaluate other options

    Manually calling methods or using @BeforeAll is less reusable or runs only once per class. Annotating methods individually is repetitive.
  4. Final Answer:

    Create a custom extension class implementing BeforeEachCallback and annotate each test class with @ExtendWith(YourExtension.class) -> Option A
  5. Quick Check:

    Custom extension + @ExtendWith on class = reusable setup [OK]
Hint: Use custom extension + @ExtendWith on class for reusable setup [OK]
Common Mistakes:
  • Calling setup manually in each test
  • Using @BeforeAll for per-test setup
  • Annotating each test method instead of class
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard