Ai-agent-instructions java-unit-test
Generates, fixes, and improves Java unit tests using JUnit 5, Mockito, and AssertJ. Handles test creation for service/controller/utility/DTO classes, debugging failing tests, refactoring legacy tests, and improving coverage. Use this skill whenever the user needs to write Java tests, fix broken tests, improve test quality, increase coverage, or work with any *Test.java files — even when they just say "test this class" or "why is this test failing".
git clone https://github.com/khumbal/ai-agent-instructions
T=$(mktemp -d) && git clone --depth=1 https://github.com/khumbal/ai-agent-instructions "$T" && mkdir -p ~/.claude/skills && cp -r "$T/.copilot/skills/java-unit-test" ~/.claude/skills/khumbal-ai-agent-instructions-java-unit-test && rm -rf "$T"
.copilot/skills/java-unit-test/SKILL.mdJava Unit Test
When to use this skill
Use when generating, fixing, or improving Java unit tests — including test creation for any class type, debugging failures, and improving coverage.
Critical constraint
Modify only test files (
src/test/java/**/*Test.java). Never change production code to make tests pass. If production code has bugs, document current behavior and add a TODO.
Conditional workflow
-
Determine your task:
Generate new tests? → Read source class → choose pattern by type:
- Utility class →
with@ParameterizedTest
/@CsvSource@MethodSource - Service class →
dependencies +@Mock
+ business scenarios@InjectMocks - Controller class →
+MockMvc
+ HTTP status/response@MockBean - Model/DTO class → Constructor, equals/hashCode, serialization
Fix failing test? → Read error message FIRST → match fix pattern:
→ CheckNullPointerException
+@Mock
initialization@InjectMocks- Mock verification fail → Use flexible matchers (
,any()
)argThat() - Assertion mismatch → Verify expectations match actual behavior
- Flaky/timing → Mock time dependencies, avoid
Thread.sleep - Spring context error → Use
not@ExtendWith(MockitoExtension.class)@SpringBootTest
Improve existing tests? → Assess quality against checklist below
- Utility class →
Test stack
- JUnit 5 with
(not@ExtendWith(MockitoExtension.class)
)@RunWith - AssertJ assertions:
(notassertThat()
)assertEquals - Mockito:
,@Mock
,@InjectMockslenient().when() - @ParameterizedTest with
/@CsvSource
for data-driven tests@MethodSource
only when Spring context is truly required@SpringBootTest
Test structure: AAA pattern
@Test void methodName_scenario_expectedBehavior() { // ARRANGE when(mockDep.call(any())).thenReturn(mockResponse); // ACT var result = service.methodName(input); // ASSERT assertThat(result).isNotNull(); verify(mockDep).call(any()); }
Code templates
See test generation patterns for complete templates per class type (Utility, Service, Controller) and common fix patterns.
Feedback loop
After writing/modifying tests:
Write tests → Run → Pass? → Done ↓ No Read error → Apply fix → Run again (loop until green)
- Run tests via
mvn test -pl module -Dtest=ClassNameTest - If fails → read error message → match to fix pattern above
- Apply fix to test code only
- Run again → repeat until all pass
- Check coverage meets threshold
When production code has bugs
@Test @DisplayName("CURRENT BEHAVIOR: returns null for invalid input (BUG: should throw)") void method_invalidInput_currentlyReturnsNull() { assertThat(service.method(invalidInput)).isNull(); // TODO: File BUG-XXX - should throw IllegalArgumentException }
Quality checklist
- Test names:
methodName_scenario_expectedBehavior - AAA pattern clearly separated
- Edge cases: null, empty, boundary values
- No
for pure unit tests@SpringBootTest - AssertJ assertions throughout
-
for multiple input/output scenarios@ParameterizedTest - Coverage > 80% for business logic
- Each test < 1 second execution
Reference files
- Test generation patterns: Complete templates per class type and common fix patterns
- Copilot prompt templates: Comment templates for guiding test generation