JUnit 5 testing
Guide Java test implementation by turning behavior requirements into focused JUnit 5 tests that use idiomatic project structure, per-test lifecycle hooks, data-driven parameterized data, assertions, mocking, human-readable organization, and build-tool validation.
When to invoke
- "Write JUnit 5 tests for this Java class."
- "Show junit 5+ best practices for parameterized tests."
- "Convert these examples to
@ParameterizedTest."
- "How should I use Mockito, tags, and nested tests in JUnit?"
Project setup
| Concern |
Rule |
| Structure |
Use standard Maven or Gradle layout; put tests in src/test/java. |
| Dependencies |
Include junit-jupiter-api, junit-jupiter-engine, and junit-jupiter-params for parameterized tests. |
| Commands |
Run mvn test or gradle test; narrow with build-tool filters when needed. |
| Class names |
Use a Test suffix, for example CalculatorTest for Calculator. |
Test structure
| Feature |
Use |
Notes |
@Test |
Standard test methods. |
One behavior per test. |
| Arrange-Act-Assert |
Test body shape. |
Keep setup, action, and verification clear. |
methodName_should_expectedBehavior_when_scenario |
Descriptive naming. |
Match existing project style if stronger. |
@BeforeEach / @AfterEach |
Per-test setup and teardown. |
Reset mutable state. |
@BeforeAll / @AfterAll |
Per-class setup and teardown. |
Static by default unless using a per-class lifecycle. |
@DisplayName |
Human-readable class or method names. |
Useful for business-readable scenarios. |
@Nested |
Group related scenarios. |
Keeps context-specific setup close to tests. |
Data-driven tests
| Source |
Use it for |
Notes |
@ParameterizedTest |
Any test run with multiple input rows. |
Pair with exactly one source. |
@ValueSource |
Simple literal strings, ints, longs, doubles, classes, or booleans. |
Best for one-parameter tests. |
@MethodSource |
Factory method returning Stream, Collection, iterable, or arguments. |
Best for computed or named cases. |
@CsvSource |
Small inline comma-separated rows. |
Keep rows readable. |
@CsvFileSource |
CSV file from the classpath. |
Use for larger stable datasets. |
@EnumSource |
Enum constants. |
Filter modes are useful for subsets. |
Assertions and exceptions
| Need |
Assertion |
| Equality |
assertEquals(expected, actual); baseline form assertEquals. |
| Truthiness |
assertTrue, assertFalse. |
| Nullability |
assertNotNull, assertNull. |
| Exception path |
assertThrows. |
| No exception path |
assertDoesNotThrow. |
| Multiple related checks |
assertAll so all assertions run before failure. |
| Fluent style |
AssertJ assertThat(...).is... only if the project already uses or accepts AssertJ. |
Import static methods from org.junit.jupiter.api.Assertions. Add descriptive messages when they make failure diagnostics clearer.
Mocking and organization
| Technique |
Use when |
Avoid |
| Mockito |
Collaborators need isolation. |
Mocking value objects or the class under test. |
@Mock |
Declare mock dependencies. |
Manual mock setup repeated across tests. |
@InjectMocks |
Construct class under test from mocks. |
Hiding complex construction that should be explicit. |
| Interfaces |
Facilitate mocking and substitutions. |
Introducing interfaces solely for trivial classes. |
| Packages |
Group tests by feature or component. |
Dumping all tests into one utility package. |
@Tag("fast"), @Tag("integration") |
Categorize suites; baseline shorthand @Tag. |
Using tags to hide slow tests instead of fixing scope. |
@TestMethodOrder(MethodOrderer.OrderAnnotation.class) and @Order |
Only when order is strictly necessary. |
Routine unit tests; independence is preferred. |
@Disabled |
Temporary skip with a reason. |
Permanent silent skips. |
Gotchas
- Do not rely on execution order: use
@TestMethodOrder only for rare ordered workflows, not normal unit tests.
- Do not mix behaviors in one parameterized test: every row should verify the same rule.
- Do not use
@SpringBootTest for ordinary unit tests: prefer plain JUnit and Mockito unless a Spring context is required.
- Do not hide failing cases with
@Disabled: include a reason and track follow-up work.
Output template
## JUnit 5 test plan
**Target:** `<class or behavior>`
**Command:** `mvn test` or `gradle test`
| Test | Annotation | Data source | Behavior verified |
| --- | --- | --- | --- |
| `<methodName_should_expectedBehavior_when_scenario>` | `@Test` or `@ParameterizedTest` | `<none / ValueSource / MethodSource / CsvSource / CsvFileSource / EnumSource>` | `<single behavior>` |
### Notes
- Lifecycle: `<BeforeEach/AfterEach/BeforeAll/AfterAll or none>`
- Assertions: `<Assertions or AssertJ>`
- Isolation: `<Mockito mocks or real collaborators>`
Quality gate
1---2name: java-junit-23description: Apply JUnit 5 best practices for Java tests, including Maven or Gradle setup, standard and parameterized tests, lifecycle hooks, assertions, Mockito isolation, tags, nested tests, and test commands. Use when asked for JUnit 5+ guidance or to write Java unit tests.4---56# JUnit 5 testing78Guide Java test implementation by turning behavior requirements into focused JUnit 5 tests that use idiomatic project structure, per-test lifecycle hooks, data-driven parameterized data, assertions, mocking, human-readable organization, and build-tool validation.910## When to invoke1112- "Write JUnit 5 tests for this Java class."13- "Show junit 5+ best practices for parameterized tests."14- "Convert these examples to `@ParameterizedTest`."15- "How should I use Mockito, tags, and nested tests in JUnit?"1617## Project setup1819| Concern | Rule |20| --- | --- |21| Structure | Use standard Maven or Gradle layout; put tests in `src/test/java`. |22| Dependencies | Include `junit-jupiter-api`, `junit-jupiter-engine`, and `junit-jupiter-params` for parameterized tests. |23| Commands | Run `mvn test` or `gradle test`; narrow with build-tool filters when needed. |24| Class names | Use a `Test` suffix, for example `CalculatorTest` for `Calculator`. |2526## Test structure2728| Feature | Use | Notes |29| --- | --- | --- |30| `@Test` | Standard test methods. | One behavior per test. |31| Arrange-Act-Assert | Test body shape. | Keep setup, action, and verification clear. |32| `methodName_should_expectedBehavior_when_scenario` | Descriptive naming. | Match existing project style if stronger. |33| `@BeforeEach` / `@AfterEach` | Per-test setup and teardown. | Reset mutable state. |34| `@BeforeAll` / `@AfterAll` | Per-class setup and teardown. | Static by default unless using a per-class lifecycle. |35| `@DisplayName` | Human-readable class or method names. | Useful for business-readable scenarios. |36| `@Nested` | Group related scenarios. | Keeps context-specific setup close to tests. |3738## Data-driven tests3940| Source | Use it for | Notes |41| --- | --- | --- |42| `@ParameterizedTest` | Any test run with multiple input rows. | Pair with exactly one source. |43| `@ValueSource` | Simple literal strings, ints, longs, doubles, classes, or booleans. | Best for one-parameter tests. |44| `@MethodSource` | Factory method returning `Stream`, `Collection`, iterable, or arguments. | Best for computed or named cases. |45| `@CsvSource` | Small inline comma-separated rows. | Keep rows readable. |46| `@CsvFileSource` | CSV file from the classpath. | Use for larger stable datasets. |47| `@EnumSource` | Enum constants. | Filter modes are useful for subsets. |4849## Assertions and exceptions5051| Need | Assertion |52| --- | --- |53| Equality | `assertEquals(expected, actual)`; baseline form `assertEquals`. |54| Truthiness | `assertTrue`, `assertFalse`. |55| Nullability | `assertNotNull`, `assertNull`. |56| Exception path | `assertThrows`. |57| No exception path | `assertDoesNotThrow`. |58| Multiple related checks | `assertAll` so all assertions run before failure. |59| Fluent style | AssertJ `assertThat(...).is...` only if the project already uses or accepts AssertJ. |6061Import static methods from `org.junit.jupiter.api.Assertions`. Add descriptive messages when they make failure diagnostics clearer.6263## Mocking and organization6465| Technique | Use when | Avoid |66| --- | --- | --- |67| Mockito | Collaborators need isolation. | Mocking value objects or the class under test. |68| `@Mock` | Declare mock dependencies. | Manual mock setup repeated across tests. |69| `@InjectMocks` | Construct class under test from mocks. | Hiding complex construction that should be explicit. |70| Interfaces | Facilitate mocking and substitutions. | Introducing interfaces solely for trivial classes. |71| Packages | Group tests by feature or component. | Dumping all tests into one utility package. |72| `@Tag("fast")`, `@Tag("integration")` | Categorize suites; baseline shorthand `@Tag`. | Using tags to hide slow tests instead of fixing scope. |73| `@TestMethodOrder(MethodOrderer.OrderAnnotation.class)` and `@Order` | Only when order is strictly necessary. | Routine unit tests; independence is preferred. |74| `@Disabled` | Temporary skip with a reason. | Permanent silent skips. |7576## Gotchas7778- **Do not rely on execution order**: use `@TestMethodOrder` only for rare ordered workflows, not normal unit tests.79- **Do not mix behaviors in one parameterized test**: every row should verify the same rule.80- **Do not use `@SpringBootTest` for ordinary unit tests**: prefer plain JUnit and Mockito unless a Spring context is required.81- **Do not hide failing cases with `@Disabled`**: include a reason and track follow-up work.8283## Output template8485```markdown86## JUnit 5 test plan8788**Target:** `<class or behavior>`89**Command:** `mvn test` or `gradle test`9091| Test | Annotation | Data source | Behavior verified |92| --- | --- | --- | --- |93| `<methodName_should_expectedBehavior_when_scenario>` | `@Test` or `@ParameterizedTest` | `<none / ValueSource / MethodSource / CsvSource / CsvFileSource / EnumSource>` | `<single behavior>` |9495### Notes96- Lifecycle: `<BeforeEach/AfterEach/BeforeAll/AfterAll or none>`97- Assertions: `<Assertions or AssertJ>`98- Isolation: `<Mockito mocks or real collaborators>`99```100101## Quality gate102103- [ ] Tests live in `src/test/java` and run with `mvn test` or `gradle test`.104- [ ] JUnit Jupiter dependencies include `junit-jupiter-api`, `junit-jupiter-engine`, and `junit-jupiter-params` when parameterized tests are used.105- [ ] Tests use `@Test` or `@ParameterizedTest` appropriately and follow Arrange-Act-Assert.106- [ ] Parameterized tests use the smallest suitable source annotation.107- [ ] Assertions are specific and include exception checks with `assertThrows` or `assertDoesNotThrow` where relevant.108- [ ] Mockito, tags, ordering, disabling, and `@Nested` are used only when they clarify the test suite.