131-java-testing-unit-testing
npx machina-cli add skill jabrena/cursor-rules-java/131-java-testing-unit-testing --openclawJava Unit testing guidelines
Review and improve Java unit tests using modern JUnit 5, AssertJ, and Mockito best practices.
Core areas: JUnit 5 annotations (@Test, @BeforeEach, @AfterEach, @DisplayName, @Nested, @ParameterizedTest), AssertJ fluent assertions (assertThat, assertThatThrownBy), Given-When-Then test structure, descriptive test naming, single-responsibility tests, test independence and isolated state, parameterized tests with @ValueSource/@CsvSource/@MethodSource, Mockito dependency mocking (@Mock, @InjectMocks, MockitoExtension), code coverage guidance (JaCoCo), package-private test visibility, code-splitting strategies (small methods, helper functions), testing anti-patterns (reflection, shared state, hard-coded values, testing implementation details), state management (immutable objects, @BeforeEach reset), error handling (assertThatThrownBy, exception messages), JSpecify null-safety (@NullMarked, @Nullable), RIGHT-BICEP coverage principles, A-TRIP test quality characteristics, and CORRECT boundary condition verification.
Prerequisites: Run ./mvnw compile or mvn compile before applying any change. If compilation fails, stop immediately and do not proceed β compilation failure is a blocking condition.
Multi-step scope: Step 1 validates the project compiles. Step 2 analyzes existing tests and categorizes issues by impact (CRITICAL, MAINTAINABILITY, PERFORMANCE, COVERAGE, RELIABILITY). Step 3 migrates to JUnit 5 with modern annotations. Step 4 adopts AssertJ for expressive assertions. Step 5 restructures tests using Given-When-Then with descriptive naming. Step 6 ensures test independence by eliminating shared state and order dependencies. Step 7 adds parameterized tests and boundary-condition coverage. Step 8 integrates Mockito mocking for external dependencies.
Before applying changes: Read the reference for detailed examples, good/bad patterns, and constraints.
Reference
For detailed guidance, examples, and constraints, see references/131-java-unit-testing.md.
Source
git clone https://github.com/jabrena/cursor-rules-java/blob/main/skills/131-java-testing-unit-testing/SKILL.mdView on GitHub Overview
This skill guides you to review, improve, and write robust Java unit tests using modern practices. It emphasizes migrating to JUnit 5, adopting AssertJ for fluent assertions, and leveraging Mockito for isolation, while enforcing Given-When-Then structure, test independence, and boundary condition checks.
How This Skill Works
It teaches converting tests to JUnit 5 annotations (@Test, @BeforeEach, @AfterEach, @DisplayName, @Nested, @ParameterizedTest), using AssertJ for fluent assertions, and applying Mockito with the MockitoExtension (@Mock, @InjectMocks). It also covers parameterized tests with @ValueSource, @CsvSource, and @MethodSource, ensures test independence via isolated state, and addresses anti-patterns like shared state and reflection-based tests.
When to Use It
- When migrating existing tests from JUnit 4 to JUnit 5.
- When adopting fluent assertions with AssertJ.
- When organizing tests with Given-When-Then and descriptive names.
- When adding parameterized tests and boundary condition coverage.
- When introducing Mockito for mocking external dependencies and ensuring test independence.
Quick Start
- Step 1: Add JUnit 5, AssertJ, and Mockito dependencies and configure the test scope in your build file.
- Step 2: Refactor a failing test to use @Test, @BeforeEach, and AssertJ assertions; ensure it runs independently.
- Step 3: Introduce a @ParameterizedTest with @ValueSource/@CsvSource and add a Mockito-based test for a collaborator.
Best Practices
- Migrate to JUnit 5 annotations and the Jupiter engine, avoiding JUnit 4 remnants.
- Use AssertJ for readable, fluent assertions rather than traditional asserts.
- Structure tests with Given-When-Then and keep tests focused (single responsibility).
- Ensure test independence by resetting state in @BeforeEach and avoiding shared mutable data.
- Incorporate parameterized tests (@ValueSource, @CsvSource, @MethodSource) and Mockito mocks with proper extensions.
Example Use Cases
- Migrating a JUnit 4 test class to JUnit 5 with @Test, @BeforeEach, and display names.
- Replacing legacy assertions with AssertJ's fluent assertThat in a service method test.
- Adding @ParameterizedTest with @ValueSource to cover multiple inputs for a validator.
- Using MockitoExtension to mock a repository and verify interactions in a unit test.
- Testing exceptions with assertThatThrownBy and validating the exception message.