Skip to content

Feature/travel game tests#32

Merged
AntonAhlqvist merged 7 commits into
mainfrom
feature/travelGameTests
Jan 14, 2026
Merged

Feature/travel game tests#32
AntonAhlqvist merged 7 commits into
mainfrom
feature/travelGameTests

Conversation

@AntonAhlqvist

@AntonAhlqvist AntonAhlqvist commented Jan 14, 2026

Copy link
Copy Markdown

Uppdaterat alla tester efter feedback från olika håll.

Summary by CodeRabbit

  • Tests
    • Added comprehensive unit test coverage for core application services and models, including initialization, journey management, event handling, transport mechanics, and traveler state management.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai

coderabbitai Bot commented Jan 14, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR adds comprehensive unit test coverage across five test suites totaling 663 new lines: BootstrapServiceTest, JourneyServiceTest, PlayerEventServiceTest, TransportTest, and TravelerTest. Tests employ JUnit 5 and Mockito to verify service initialization logic, journey management, event application, transport mechanics, and traveler state transitions.

Changes

Cohort / File(s) Summary
Service Tests
src/test/java/org/example/BootstrapServiceTest.java
Unit tests for BootstrapService.initialize: validates seeding check via mocked count query, transaction rollback on query exception, and file-not-found handling when database unseeded
src/test/java/org/example/JourneyServiceTest.java
src/test/java/org/example/PlayerEventServiceTest.java
Domain Model Tests
src/test/java/org/example/TransportTest.java
Range validation tests for Transport.rollDistance(): asserts BUSS (1–6), TRAIN (2–12), and AIRPLANE (3–18) returns stay within expected bounds across 50 iterations per type
src/test/java/org/example/TravelerTest.java

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • Feature/journey service #19: JourneyServiceTest directly exercises JourneyService behaviors and validates route/transport/cost logic implemented in that PR.
  • Feature/db entity #7: The new tests target behavior and persistence of Journey/Traveler/Transport entities and transaction logic foundationally introduced in that PR.
  • Feature/player movement #6: Both PRs touch Traveler and Transport classes—this PR adds comprehensive unit tests while that PR modifies their implementations and APIs.

Poem

🐰 Hop, hop! New tests now guard each flow—
Bootstrap seeds, journeys start and go,
Transport rolls and travelers advance,
Coverage blooms with every test's dance!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Feature/travel game tests' accurately describes the main changeset, which adds comprehensive unit tests for travel-game-related services (BootstrapService, JourneyService, PlayerEventService, Transport, and Traveler).
Docstring Coverage ✅ Passed Docstring coverage is 92.31% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/test/java/org/example/TransportTest.java`:
- Around line 17-40: The test rollDistance_returnsValidRange is tautological
because it mocks Transport.rollDistance() to fixed values and then asserts those
values fall within ranges; replace the mocks with real Transport instances (or
inject a mock Random source if Transport uses one) so rollDistance()
implementation is exercised: instantiate Transport objects for "BUSS", "TRAIN",
"AIRPLANE" in the test method rollDistance_returnsValidRange (or refactor
Transport to accept a Random and supply a controllable/mock Random) and run the
loop asserting returned values fall within the expected bounds for each type
instead of stubbing rollDistance().
🧹 Nitpick comments (3)
src/test/java/org/example/BootstrapServiceTest.java (2)

68-77: Redundant null assertion and loose message check.

The assertNotNull(ex) on line 74 is redundant since assertThrows already guarantees a non-null exception is returned (it would fail otherwise). Additionally, the message assertion checks for either "failed to bootstrap database" or "File not found", but the mock throws "table missing"—this works only if BootstrapService wraps the exception with a new message.

♻️ Suggested simplification
         RuntimeException ex = assertThrows(RuntimeException.class, service::initialize);

         verify(tx).begin();
         verify(tx).isActive();
         verify(tx).rollback();

-        assertNotNull(ex);
         assertTrue(ex.getMessage().contains("failed to bootstrap database") ||
-            ex.getMessage().contains("File not found"));
+            ex.getMessage().contains("File not found") ||
+            ex.getMessage().contains("table missing"));

93-102: Same redundant null assertion.

Similar to the previous test, assertNotNull(ex) is unnecessary after assertThrows.

♻️ Suggested simplification
         RuntimeException ex = assertThrows(RuntimeException.class, service::initialize);

         verify(tx).begin();
         verify(tx).isActive();
         verify(tx).rollback();

-        assertNotNull(ex);
         assertTrue(ex.getMessage().contains("File not found") ||
             ex.getMessage().contains("failed to bootstrap database"));
src/test/java/org/example/PlayerEventServiceTest.java (1)

40-48: Tautological size check and flaky test concern.

The condition events.size() >= 0 is always true for any List—list sizes cannot be negative. Additionally, since event generation appears to be probabilistic, a single test run might not exercise all branches reliably.

♻️ Suggested improvement
 `@Test`
-void eventCountWithinBounds() {
+@RepeatedTest(10)
+void eventCountWithinBounds() {
     Traveler traveler = dummyTraveler();
     PlayerEventService service = new PlayerEventService();

     List<PlayerEventService.EventResult> events = service.applyEndOfTurnEvents(traveler);

-    assertTrue(events.size() >= 0 && events.size() <= 2);
+    assertTrue(events.size() <= 2, "Expected at most 2 events, got: " + events.size());
 }
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d0dc857 and c68e602.

📒 Files selected for processing (5)
  • src/test/java/org/example/BootstrapServiceTest.java
  • src/test/java/org/example/JourneyServiceTest.java
  • src/test/java/org/example/PlayerEventServiceTest.java
  • src/test/java/org/example/TransportTest.java
  • src/test/java/org/example/TravelerTest.java
🔇 Additional comments (21)
src/test/java/org/example/TravelerTest.java (7)

1-13: LGTM!

The helper method dummyLocation provides good test isolation by creating minimal Location objects without unnecessary dependencies.


20-27: LGTM!

Constructor position test correctly validates that playerPosX and playerPosY are initialized from the location coordinates.


34-38: LGTM!

Initial state test properly verifies that a new Traveler is not travelling by default.


45-55: LGTM!

Journey start test validates both the travelling state and remaining distance are set correctly.


62-72: LGTM!

The advance test correctly verifies distance reduction, turn count increment, and continued travelling state.


79-90: LGTM!

Journey completion test validates the edge case where advance distance exceeds remaining distance, properly checking that travelling stops and location updates.


97-120: LGTM!

Payment tests properly validate both successful payment and the exception case for insufficient funds. Good use of assertThrows to verify both the exception type and message.

src/test/java/org/example/BootstrapServiceTest.java (2)

27-36: LGTM!

Well-structured test setup with properly mocked JPA components. The @BeforeEach ensures clean state for each test.


43-53: LGTM!

This test correctly verifies that when the database is already seeded (count >= 1), no transaction is started and no SQL is executed.

src/test/java/org/example/JourneyServiceTest.java (7)

37-42: LGTM!

Clean setup with appropriate dependency mocking for the service under test.


49-82: LGTM!

Comprehensive test that validates the happy path for starting a journey, including proper setup of mocked route, transport, and transport links. Good verification of journey state and associations.


90-119: LGTM!

Good boundary test that verifies the service prevents starting a new journey when already travelling. The exception message assertion ensures the error is user-friendly.


126-162: LGTM!

Well-designed test that verifies transport restrictions are enforced. Creates both allowed and disallowed transports to ensure the validation logic works correctly.


169-202: LGTM!

Good test for the insufficient funds scenario. Properly sets up a traveler with less money than the transport cost.


210-251: LGTM!

Thorough test for journey continuation that properly mocks the database query to return an existing journey. Good verification of state consistency.


258-299: LGTM!

Good test coverage for findPossibleMoves. Verifies that multiple transports on a single route correctly expand to multiple PossibleMoves entries.

src/test/java/org/example/PlayerEventServiceTest.java (5)

14-18: LGTM!

Good helper method that creates a traveler with sufficient funds for testing event scenarios.


25-33: LGTM!

Basic smoke test ensures the service can be called without throwing exceptions.


55-62: LGTM!

Good invariant test that ensures money never goes negative after events are applied.


69-80: LGTM!

Properly validates that all generated events have valid types and positive amounts.


87-97: LGTM!

Good validation that all events have messages. This ensures UI/logging can always display event information.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment on lines +17 to +40
@Test
void rollDistance_returnsValidRange() {
Transport buss = mock(Transport.class);
when(buss.getType()).thenReturn("BUSS");
when(buss.rollDistance()).thenAnswer(invocation -> 4);

Transport train = mock(Transport.class);
when(train.getType()).thenReturn("TRAIN");
when(train.rollDistance()).thenAnswer(invocation -> 6);

Transport airplane = mock(Transport.class);
when(airplane.getType()).thenReturn("AIRPLANE");
when(airplane.rollDistance()).thenAnswer(invocation -> 9);

for (int i = 0; i < 50; i++) {
int bussRoll = buss.rollDistance();
int trainRoll = train.rollDistance();
int airplaneRoll = airplane.rollDistance();

assertTrue(bussRoll >= 1 && bussRoll <= 6, "BUSS roll utanför spann: " + bussRoll);
assertTrue(trainRoll >= 2 && trainRoll <= 12, "TRAIN roll utanför spann: " + trainRoll);
assertTrue(airplaneRoll >= 3 && airplaneRoll <= 18, "AIRPLANE roll utanför spann: " + airplaneRoll);
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Test is tautological and provides no real coverage.

This test mocks Transport.rollDistance() to return fixed values (4, 6, 9), then asserts those same fixed values fall within expected ranges. The test only verifies that Mockito returns what you told it to return—it never exercises the actual Transport.rollDistance() implementation.

To properly test the randomness bounds, you should either:

  1. Use real Transport instances and run multiple iterations to statistically verify the range, or
  2. If Transport delegates to a random source, inject a mock random generator and verify the calculation logic.
🧪 Example approach using real instances
`@Test`
void rollDistance_returnsValidRange() {
    Transport buss = new Transport("BUSS", /* other params */);
    Transport train = new Transport("TRAIN", /* other params */);
    Transport airplane = new Transport("AIRPLANE", /* other params */);

    for (int i = 0; i < 50; i++) {
        int bussRoll = buss.rollDistance();
        int trainRoll = train.rollDistance();
        int airplaneRoll = airplane.rollDistance();

        assertTrue(bussRoll >= 1 && bussRoll <= 6, "BUSS roll utanför spann: " + bussRoll);
        assertTrue(trainRoll >= 2 && trainRoll <= 12, "TRAIN roll utanför spann: " + trainRoll);
        assertTrue(airplaneRoll >= 3 && airplaneRoll <= 18, "AIRPLANE roll utanför spann: " + airplaneRoll);
    }
}
🤖 Prompt for AI Agents
In `@src/test/java/org/example/TransportTest.java` around lines 17 - 40, The test
rollDistance_returnsValidRange is tautological because it mocks
Transport.rollDistance() to fixed values and then asserts those values fall
within ranges; replace the mocks with real Transport instances (or inject a mock
Random source if Transport uses one) so rollDistance() implementation is
exercised: instantiate Transport objects for "BUSS", "TRAIN", "AIRPLANE" in the
test method rollDistance_returnsValidRange (or refactor Transport to accept a
Random and supply a controllable/mock Random) and run the loop asserting
returned values fall within the expected bounds for each type instead of
stubbing rollDistance().

@AntonAhlqvist
AntonAhlqvist merged commit f755ac3 into main Jan 14, 2026
2 checks passed
@AntonAhlqvist
AntonAhlqvist deleted the feature/travelGameTests branch January 14, 2026 20:47
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.

1 participant