Java Testing Skill
Activation Contract
Use this skill for Java tests: unit tests, JUnit/Mockito/AssertJ examples, characterization tests, Golden Master tests, seams, or dependency-breaking.
Do not use for non-Java projects, generic strategy, frontend/E2E, performance, security, or refactoring without a testing objective.
Responsibility
Own Java test workflow: detect the local stack, choose the smallest safe technique, create or propose tests, and explain seam/dependency tradeoffs. The caller owns product behavior, dependency approval, and running project commands when validation exists.
Required Context
Before writing tests, inspect or ask for:
- Java version, build tool, and test dependencies.
- Existing test naming, package layout, assertions, fixtures, and mocking style.
- Class under test, observable behavior, collaborators, and failure/edge cases.
- For legacy code: change point, test point, hidden dependencies, and whether the seam is for Sensing or Separation.
Hard Rules
- Detect Java level, build tool, JUnit/Mockito versions, assertion style, and dependency management independently.
- Preserve the project test stack unless a dependency change is explicitly needed and justified.
- Prefer the simplest useful test: pure unit test first, Mockito only across real boundaries, Spring/context tests only when the framework behavior is the subject.
- For clean code, test behavior and avoid over-verifying collaborators.
- For existing untested or hard-to-test code, use Cover → Modify → Refactor: characterize current behavior before changing it.
- When breaking dependencies, name whether the seam is for Sensing or Separation.
- Generated examples must be complete, compilable, and match local package, naming, and style conventions.
- Do not add or upgrade JUnit, Mockito, AssertJ, PowerMock, or ApprovalTests unless the existing stack cannot support the required test and the tradeoff is stated.
- Do not modify production behavior before a safety test exists for legacy code.
Decision Gates
| Situation |
Route |
| Clean, injectable class needs tests |
Use Simple Unit Tests below. |
| Existing code has no tests but is easy to instantiate |
Write characterization tests first, then improve. |
| Constructor/static/global/framework dependencies block testing |
Use references/quick-decision-flow.md and dependency-breaking references. |
| Dependency setup is missing or unclear |
Read references/dependency-setup.md before adding imports or build snippets. |
| Golden Master or ApprovalTests is needed |
Read references/characterization-tests.md, then references/approvaltests-setup.md before creating baselines. |
| Static/final mocking or captors are needed |
Read references/mockito-patterns.md before choosing Mockito features. |
| Large legacy cluster or unclear effect propagation |
Read references/advanced-patterns.md for pinch points, effect sketches, and hot spots. |
Execution Steps
- Detect local Java test stack and conventions.
- Identify behavior and smallest observable test point.
- Select a route; load only the referenced file needed.
- For legacy code, characterize current behavior before production changes.
- Write focused tests matching local style; avoid over-mocking.
- State seam/dependency tradeoffs, including Sensing vs Separation.
- Report validation performed or command to run.
Simple Unit Tests
- Follow the
code-conventions skill as the general contract; the rules below are its Java specifics.
- Place tests under
src/test/java/ mirroring the source package.
- Name classes
{ClassName}Test and methods should{Behavior}When{Condition} unless the project already uses another convention.
- Split every non-trivial test body with
// Given, // When, // Then section markers; avoid other comments/Javadocs.
- For JUnit 5 + Mockito, use
@ExtendWith(MockitoExtension.class), @Mock, and @InjectMocks only when constructor setup adds noise.
- Prefer AssertJ
assertThat() / assertThatThrownBy() when already present; WithAssertions is acceptable if it matches project style.
- For complex objects/DTOs, assert the whole object with
usingRecursiveComparison() or ApprovalTests instead of field-by-field cascades.
- Use parameterized tests for meaningful input matrices, and
ArgumentCaptor only when the passed object is the behavior under test.
Legacy Testing Flow
- Identify change points.
- Find test points with effect sketches.
- Break dependencies only where needed for Sensing or Separation.
- Write characterization tests that document what the code does now, in a dedicated permanent
{ClassName}CharacterizationTest class separate from intent-revealing unit tests.
- Modify and refactor behind the safety net.
References
Load progressively; do not read the full catalog by default.
Use references/ to understand when and why to apply a technique. Use assets/examples/ only as copyable starting points: adapt package names, dependencies, naming, and project conventions before committing.
| Reference |
Load when |
references/dependency-setup.md |
Dependency setup or version compatibility is unclear. |
references/mockito-patterns.md |
Mockito annotations, captors, verification, static/final mocking, or interaction boundaries are needed. |
references/characterization-tests.md |
Existing behavior must be locked before modification, including Golden Master tests. |
references/approvaltests-setup.md |
ApprovalTests setup or baseline workflow is needed. |
references/seam-model.md |
Seams and enabling points must be classified before breaking dependencies. |
references/dependency-breaking.md |
Constructor, interface, override, parameter adaptation, or global-reference techniques are needed. |
references/quick-decision-flow.md |
The code is hard to test and you need a first route. |
references/sensing-separation.md |
Decide whether the seam observes behavior or separates dependencies. |
references/pass-null-subclass-override.md |
Pass Null, null object, subclass-and-override, or extract-and-override is the likely seam. |
references/sprout-wrap-techniques.md |
Risky legacy additions call for Sprout Method/Class or Wrap Method/Class. |
references/method-object-skin-wrap.md |
Long methods, API skin wrapping, or method-object extraction is needed. |
references/tdd-legacy.md |
The task asks for TDD while modifying existing legacy Java. |
references/advanced-patterns.md |
Pinch points, effect sketches, God classes, hot spots, or scratch refactoring are needed. |
assets/examples/ExampleServiceTest.java |
Service test template with JUnit 5, Mockito, and AssertJ. |
assets/examples/ExampleConfigTest.java |
Configuration/value-object style example. |
assets/examples/ExampleHandlerTest.java |
Handler/controller collaborator example. |
assets/examples/ExampleCacheTest.java |
Cache/stateful behavior example. |
assets/examples/ExampleListenerTest.java |
Listener/event-driven example. |
Output Contract
Return:
- Chosen route and references used.
- Detected Java test stack and conventions.
- Files changed or proposed.
- Tests added, including behaviors and edge cases covered.
- Dependency/seam tradeoffs, including Sensing vs Separation when applicable.
- Validation performed or recommended command.
1---2name: java-testing3description: Trigger: Java tests, JUnit, Mockito, AssertJ, legacy code, characterization tests, seams. Generate and retrofit Java tests safely.4license: MIT5---67# Java Testing Skill89## Activation Contract1011Use this skill for Java tests: unit tests, JUnit/Mockito/AssertJ examples, characterization tests, Golden Master tests, seams, or dependency-breaking.1213Do not use for non-Java projects, generic strategy, frontend/E2E, performance, security, or refactoring without a testing objective.1415## Responsibility1617Own Java test workflow: detect the local stack, choose the smallest safe technique, create or propose tests, and explain seam/dependency tradeoffs. The caller owns product behavior, dependency approval, and running project commands when validation exists.1819## Required Context2021Before writing tests, inspect or ask for:2223- Java version, build tool, and test dependencies.24- Existing test naming, package layout, assertions, fixtures, and mocking style.25- Class under test, observable behavior, collaborators, and failure/edge cases.26- For legacy code: change point, test point, hidden dependencies, and whether the seam is for Sensing or Separation.2728## Hard Rules2930- Detect Java level, build tool, JUnit/Mockito versions, assertion style, and dependency management independently.31- Preserve the project test stack unless a dependency change is explicitly needed and justified.32- Prefer the simplest useful test: pure unit test first, Mockito only across real boundaries, Spring/context tests only when the framework behavior is the subject.33- For clean code, test behavior and avoid over-verifying collaborators.34- For existing untested or hard-to-test code, use Cover → Modify → Refactor: characterize current behavior before changing it.35- When breaking dependencies, name whether the seam is for Sensing or Separation.36- Generated examples must be complete, compilable, and match local package, naming, and style conventions.37- Do not add or upgrade JUnit, Mockito, AssertJ, PowerMock, or ApprovalTests unless the existing stack cannot support the required test and the tradeoff is stated.38- Do not modify production behavior before a safety test exists for legacy code.3940## Decision Gates4142| Situation | Route |43|---|---|44| Clean, injectable class needs tests | Use Simple Unit Tests below. |45| Existing code has no tests but is easy to instantiate | Write characterization tests first, then improve. |46| Constructor/static/global/framework dependencies block testing | Use `references/quick-decision-flow.md` and dependency-breaking references. |47| Dependency setup is missing or unclear | Read `references/dependency-setup.md` before adding imports or build snippets. |48| Golden Master or ApprovalTests is needed | Read `references/characterization-tests.md`, then `references/approvaltests-setup.md` before creating baselines. |49| Static/final mocking or captors are needed | Read `references/mockito-patterns.md` before choosing Mockito features. |50| Large legacy cluster or unclear effect propagation | Read `references/advanced-patterns.md` for pinch points, effect sketches, and hot spots. |5152## Execution Steps53541. Detect local Java test stack and conventions.552. Identify behavior and smallest observable test point.563. Select a route; load only the referenced file needed.574. For legacy code, characterize current behavior before production changes.585. Write focused tests matching local style; avoid over-mocking.596. State seam/dependency tradeoffs, including Sensing vs Separation.607. Report validation performed or command to run.6162## Simple Unit Tests6364- Follow the `code-conventions` skill as the general contract; the rules below are its Java specifics.65- Place tests under `src/test/java/` mirroring the source package.66- Name classes `{ClassName}Test` and methods `should{Behavior}When{Condition}` unless the project already uses another convention.67- Split every non-trivial test body with `// Given`, `// When`, `// Then` section markers; avoid other comments/Javadocs.68- For JUnit 5 + Mockito, use `@ExtendWith(MockitoExtension.class)`, `@Mock`, and `@InjectMocks` only when constructor setup adds noise.69- Prefer AssertJ `assertThat()` / `assertThatThrownBy()` when already present; `WithAssertions` is acceptable if it matches project style.70- For complex objects/DTOs, assert the whole object with `usingRecursiveComparison()` or ApprovalTests instead of field-by-field cascades.71- Use parameterized tests for meaningful input matrices, and `ArgumentCaptor` only when the passed object is the behavior under test.7273## Legacy Testing Flow74751. Identify change points.762. Find test points with effect sketches.773. Break dependencies only where needed for Sensing or Separation.784. Write characterization tests that document what the code does now, in a dedicated permanent `{ClassName}CharacterizationTest` class separate from intent-revealing unit tests.795. Modify and refactor behind the safety net.8081## References8283Load progressively; do not read the full catalog by default.84Use `references/` to understand when and why to apply a technique. Use `assets/examples/` only as copyable starting points: adapt package names, dependencies, naming, and project conventions before committing.8586| Reference | Load when |87|---|---|88| `references/dependency-setup.md` | Dependency setup or version compatibility is unclear. |89| `references/mockito-patterns.md` | Mockito annotations, captors, verification, static/final mocking, or interaction boundaries are needed. |90| `references/characterization-tests.md` | Existing behavior must be locked before modification, including Golden Master tests. |91| `references/approvaltests-setup.md` | ApprovalTests setup or baseline workflow is needed. |92| `references/seam-model.md` | Seams and enabling points must be classified before breaking dependencies. |93| `references/dependency-breaking.md` | Constructor, interface, override, parameter adaptation, or global-reference techniques are needed. |94| `references/quick-decision-flow.md` | The code is hard to test and you need a first route. |95| `references/sensing-separation.md` | Decide whether the seam observes behavior or separates dependencies. |96| `references/pass-null-subclass-override.md` | Pass Null, null object, subclass-and-override, or extract-and-override is the likely seam. |97| `references/sprout-wrap-techniques.md` | Risky legacy additions call for Sprout Method/Class or Wrap Method/Class. |98| `references/method-object-skin-wrap.md` | Long methods, API skin wrapping, or method-object extraction is needed. |99| `references/tdd-legacy.md` | The task asks for TDD while modifying existing legacy Java. |100| `references/advanced-patterns.md` | Pinch points, effect sketches, God classes, hot spots, or scratch refactoring are needed. |101| `assets/examples/ExampleServiceTest.java` | Service test template with JUnit 5, Mockito, and AssertJ. |102| `assets/examples/ExampleConfigTest.java` | Configuration/value-object style example. |103| `assets/examples/ExampleHandlerTest.java` | Handler/controller collaborator example. |104| `assets/examples/ExampleCacheTest.java` | Cache/stateful behavior example. |105| `assets/examples/ExampleListenerTest.java` | Listener/event-driven example. |106107## Output Contract108109Return:110111- Chosen route and references used.112- Detected Java test stack and conventions.113- Files changed or proposed.114- Tests added, including behaviors and edge cases covered.115- Dependency/seam tradeoffs, including Sensing vs Separation when applicable.116- Validation performed or recommended command.