Skip to content

test: add direct unit test for ProjectRepository - #53

Merged
dmccoystephenson merged 2 commits into
mainfrom
feat/project-repository-test
Sep 26, 2026
Merged

dmccoystephenson merged 2 commits into
mainfrom
feat/project-repository-test

Conversation

@dmccoystephenson

Copy link
Copy Markdown
Member

Summary

  • A new ProjectRepositoryTest is added under src/test/java/com/preponderous/parpt/repo/, constructing ProjectRepository directly with a Mockito-mocked ProjectJsonReaderWriter (no Spring context, no filesystem).
  • Each behaviour listed in Add a direct unit test for ProjectRepository #51 is asserted directly:
    • the constructor seeds the in-memory list from readJson() and does not write;
    • findAll() returns a defensive copy;
    • add(...) on a duplicate name throws NameTakenException, leaves the list unchanged and never calls writeJson;
    • remove(...) on an unknown name throws ProjectNotFoundException (message asserted) and never calls writeJson;
    • successful add, remove and clear each persist exactly once, with the persisted contents asserted.
  • findByName hit/miss cases are also covered.
  • Because writeJson receives the repository's own mutable list, each call's contents are snapshotted in a doAnswer so that the assertions reflect the list at call time rather than at verification time.
  • Characterization only; no production code is changed.

Test plan

  • ./gradlew test -Dorg.gradle.java.home=/usr/lib/jvm/java-21-openjdk-amd64: 114 tests executed, 0 failures, 0 errors (9 in ProjectRepositoryTest), counted from build/test-results/test/*.xml
  • CI (Build and Test, CI Pipeline) green on this branch

Deferred issues (skip reasons)

Closes #51

This PR description was drafted during a Gardener session (https://github.com/Stephenson-Software/gardener).

🤖 Generated with Claude Code


drafted by Claude on behalf of Daniel Stephenson

Construct ProjectRepository with a mocked ProjectJsonReaderWriter and
assert seeding from readJson, the defensive copy from findAll, duplicate
and unknown-name failures leaving state unpersisted, and exactly one
writeJson per successful add/remove/clear.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

Test Results

114 tests  +9   114 ✅ +9   1s ⏱️ ±0s
 18 suites +1     0 💤 ±0 
 18 files   +1     0 ❌ ±0 

Results for commit a40ad59. ± Comparison against base commit a4a8205.

♻️ This comment has been updated with latest results.

Mockito.* already brings ArgumentMatchers.anyList into scope.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dmccoystephenson

Copy link
Copy Markdown
Member Author

Self-review rubric (head a40ad59):

  • Scope: PASS — gh pr diff 53 --name-only lists only src/test/java/com/preponderous/parpt/repo/ProjectRepositoryTest.java; no production, formatting or doc churn.
  • Tests-new: PASS — no new public production methods; every public ProjectRepository method (findAll, clear, add, remove, findByName, constructor) is now exercised directly by at least one test.
  • Tests-fix: N/A — no bug fix. As an empirical substitute, findAll() was temporarily mutated to return projects; locally: findAll_ShouldReturnDefensiveCopy FAILED (1 of 9), then PASSED after the mutation was reverted. So the defensive-copy assertion is observable rather than vacuous.
  • Sibling structure: PASS — follows MarkdownFormatterTest (@ExtendWith(MockitoExtension.class), @Mock, @BeforeEach construction) and the repo package's AssertJ plus methodName_ShouldExpectedBehavior naming from ProjectJsonReaderWriterImplTest.
  • Sibling renames: N/A — nothing renamed.
  • Docs: PASS — README/CONTRIBUTING describe commands and ./gradlew test; neither is affected by a new test class.
  • Issue resolution: PASS — all five bullets in Add a direct unit test for ProjectRepository #51 are asserted (seeding, defensive copy, duplicate-name no-write, unknown-name no-write, exactly-once writeJson for add/remove/clear).
  • CI / manual validation: PASS — ./gradlew test on JDK 21 locally executed 114 tests, 0 failures, 0 errors (from build/test-results/test/*.xml), and build (21), test and Test Results are green on the PR head.
  • Shell command tests / Round-trip coverage / I/O behind an interface: N/A — no command, domain field or I/O code is touched.

Findings:

  • src/test/java/com/preponderous/parpt/repo/ProjectRepositoryTest.java:15 — a redundant import static org.mockito.ArgumentMatchers.anyList; (already covered by Mockito.*) was found and removed in a40ad59.
  • src/test/java/com/preponderous/parpt/repo/ProjectRepositoryTest.java:37 — the writeJson stub is lenient() because the constructor, duplicate-name, unknown-name and findByName tests never write; under strict stubs these tests would otherwise fail with UnnecessaryStubbingException. This is intentional.
  • Out of diff: ProjectRepository's constructor stores the list returned by readJson() without copying it, so it relies on ProjectJsonReaderWriterImpl returning a mutable list. The test stubs a mutable ArrayList to match current behaviour; no production change is proposed in this characterization cycle.

Characterization-only PR; ready to merge once no further review comments arrive.

This review was drafted during a Gardener session (https://github.com/Stephenson-Software/gardener).


drafted by Claude on behalf of Daniel Stephenson

@dmccoystephenson
dmccoystephenson merged commit 5f56cb8 into main Sep 26, 2026
3 checks passed
@dmccoystephenson
dmccoystephenson deleted the feat/project-repository-test branch September 26, 2026 01:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add a direct unit test for ProjectRepository

1 participant