Step-by-step instructions

These instructions follow on from what was achieved in the previous lesson.

Add integration test to app subproject

  1. in app’s build script, add a new testImplementation dependency on spring-boot-starter-test

  2. configure test task to use JUnit 5 (also known as JUnit Jupiter)

    testing {
        suites {
            named("test", JvmTestSuite::class) {
  3. under src create directories test/java/com/tomgregory/maxirail

  4. add a class

    package com.tomgregory.maxirail;
    import org.junit.jupiter.api.Test;
    import org.junit.jupiter.api.extension.ExtendWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.http.MediaType;
    import org.springframework.test.context.junit.jupiter.SpringExtension;
    import org.springframework.test.web.servlet.MockMvc;
    import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
    import static org.hamcrest.Matchers.hasSize;
    import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
    import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
    public class MaxiRailIT {
        private MockMvc mockMvc;
        public void getsAllTrainTimes() throws Exception {
                    .andExpect(jsonPath("$", hasSize(4)))
  5. run ./gradlew test and see that the test passes

  6. view test report in build directory of app subproject

Add unit test to service subproject

  1. in service’s build script configure test task to use JUnit 5 (also known as JUnit Jupiter)

    testing {
        suites {
            named("test", JvmTestSuite::class) {
  2. under src create directories test/java/com/tomgregory/maxirail/service

  3. add a class

    package com.tomgregory.maxirail.service;
    import org.junit.jupiter.api.Test;
    import static org.junit.jupiter.api.Assertions.assertEquals;
    public class TrainTimeServiceTest {
        public void swapsDestinationStationToUppercase() {
            TrainTimeService trainTimeService = new TrainTimeService();
            assertEquals("BRIGHTON", trainTimeService.getTrainTimes().get(0).destinationStation());
            assertEquals("BRIGHTON", trainTimeService.getTrainTimes().get(1).destinationStation());
            assertEquals("LONDON", trainTimeService.getTrainTimes().get(2).destinationStation());
            assertEquals("LONDON", trainTimeService.getTrainTimes().get(3).destinationStation());
  4. run the test with ./gradlew test and see it fail

  5. make the test pass by updating the destination station names in

    package com.tomgregory.maxirail.service;
    import com.tomgregory.maxirail.model.TrainTime;
    import org.springframework.stereotype.Service;
    import java.time.LocalTime;
    import java.util.Arrays;
    import java.util.List;
    public class TrainTimeService {
        public List<TrainTime> getTrainTimes() {
            return Arrays.asList(
                    new TrainTime("London", "BRIGHTON", LocalTime.of(9, 30), LocalTime.of(10, 30)),
                    new TrainTime("London", "BRIGHTON", LocalTime.of(15, 0), LocalTime.of(16, 0)),
                    new TrainTime("Brighton", "LONDON", LocalTime.of(11, 0), LocalTime.of(12, 0)),
                    new TrainTime("Brighton", "LONDON", LocalTime.of(16, 30), LocalTime.of(17, 30))
  6. run the test again with ./gradlew test --console=verbose. This time it passes.

  7. note that it also runs tests against the app subproject. You can avoid that by running the test task specifically on the service subproject, using the fully qualified task name.

  8. run ./gradlew service:test --console=verbose

Awesome! You now know how and when to execute tasks against specific subprojects.

GitHub repository

The gradle-multi-project-masterclass repository contains the final code solution for lessons 2-5.