Unit Testing
Domain driven design is intended for complex business domains, and so testing is obviously important. In this part of the tutorial we’ll cover unit testing, later on we’ll look at integration testing.
Ex 6.1: Unit test the default time when booking visits
The "Book Visit" action has a default time of 9am the next morning. In this section we’ll write a unit test to verify this logic, using Mockito to "mock the clock".
Solution
git checkout tags/3.1.0/06-01-unit-test-bookVisit-default-time
mvn clean install
mvn -pl webapp spring-boot:run -Dspring-boot.run.jvmArguments="-Dspring.profiles.active=dev"
Tasks
-
add test dependencies to the
petclinic-module-visits
maven module:module-visits/pom.xml<dependency> <groupId>org.apache.causeway.testing</groupId> <artifactId>causeway-testing-unittestsupport-applib</artifactId> <scope>test</scope> </dependency>
-
add the test:
@ExtendWith(MockitoExtension.class) (1)
public class PetOwner_bookVisit_Test {
@Mock ClockService mockClockService; (2)
@Mock VirtualClock mockVirtualClock; (2)
@BeforeEach
void setup() {
Mockito.when(mockClockService.getClock()).thenReturn(mockVirtualClock); (3)
}
@Nested
class default1 {
@Test
void defaults_to_9am_tomorrow_morning() {
// given
PetOwner_bookVisit mixin = new PetOwner_bookVisit(null);
mixin.clockService = mockClockService; (4)
LocalDateTime now = LocalDateTime.of(2024, 5, 26, 16, 37, 45);
// expecting
Mockito.when(mockVirtualClock.nowAsLocalDate()) (5)
.thenReturn(now.toLocalDate());
// when
LocalDateTime localDateTime = mixin.default1Act();
// then
Assertions.assertThat(localDateTime) (6)
.isEqualTo(LocalDateTime.of(2024,5,27,9,0,0));
}
}
}
1 | Instructs JUnit to use Mockito for mocking. |
2 | mocks the ClockService , and mocks the VirtualClock returned by the ClockService .
Automatically provisioned by Mockito. |
3 | makes the mock ClockService return the mock VirtualClock . |
4 | inject the mock clock into the domain object |
5 | sets up expectations for this scenario on the mock VirtualClock |
6 | use AssertJ to assert the expected value |
Unit tests should have a suffix "_Test", to distinguish them from integration tests. The top-level pom configures Maven surefire to run the unit tests first and then integration tests as a separate execution. |
Optional Exercises
If you decide to do these optional exercises, make the changes on a git branch so that you can resume with the main flow of exercises later. |
-
Write a similar unit test to verify the validation logic that visits cannot be in the past.
-
Introduce a meta-annotation
@VisitedAt
, and move the validation logic into a Specification. Verify that the app still works, and write a unit test to check your specification.