Working with Testing

1. Using @SpringBootTest for Integration Tests

Example: Integration test with MockMvc

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
class OrderApiIT {
  @Autowired MockMvc mvc;
  @Test void getOrder() throws Exception {
    mvc.perform(get("/api/orders/1"))
       .andExpect(status().isOk())
       .andExpect(jsonPath("$.id").value(1));
  }
}
WebEnvironment Description
MOCK (default) Mock servlet, no real port
RANDOM_PORT Real Tomcat, random port
DEFINED_PORT Real Tomcat, configured port
NONE No web environment

2. Using @WebMvcTest for Controller Tests

Example: Slice test for controller layer

@WebMvcTest(OrderController.class)
class OrderControllerTests {
  @Autowired MockMvc mvc;
  @MockBean OrderService svc;
  @Test void create() throws Exception {
    when(svc.create(any())).thenReturn(new OrderDto(1L));
    mvc.perform(post("/api/orders").contentType(MediaType.APPLICATION_JSON)
       .content("{\"items\":[]}"))
       .andExpect(status().isCreated());
  }
}

3. Using @DataJpaTest for Repository Tests

Example: Repository test against real database

@DataJpaTest
@AutoConfigureTestDatabase(replace = Replace.NONE) // use real DB
class OrderRepositoryTests {
  @Autowired OrderRepository repo;
  @Autowired TestEntityManager em;
  @Test void findsByReference() {
    em.persist(new Order("REF-1"));
    assertThat(repo.findByReference("REF-1")).isPresent();
  }
}

4. Using @MockBean for Mocking Dependencies

Annotation Use
@MockBean Replace bean with Mockito mock
@SpyBean Wrap real bean as spy
Spring 6.2+ @MockitoBean Replacement for @MockBean

5. Using MockMvc for REST API Testing

Method Use
perform(get/post/...) Issue request
andExpect(status().isOk()) Status assertion
andExpect(jsonPath("$.field")) JSON path assertion
andExpect(content().json(...)) Full JSON match
andDo(print()) Debug output
andReturn().getResponse() Capture response

6. Testing with TestRestTemplate

Example: HTTP client integration test

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class HttpClientIT {
  @Autowired TestRestTemplate rest;
  @Test void list() {
    ResponseEntity<OrderDto[]> resp = rest.getForEntity("/api/orders", OrderDto[].class);
    assertEquals(HttpStatus.OK, resp.getStatusCode());
  }
}

7. Using @Sql for Test Data Setup

Example: Load and clean SQL test data

@SpringBootTest
@Sql(scripts = "/test-data/orders.sql",
     executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
@Sql(scripts = "/test-data/cleanup.sql",
     executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
class OrderTests { /* … */ }

8. Configuring Test Properties (@TestPropertySource)

Example: Override properties in test

@SpringBootTest
@TestPropertySource(properties = {
  "app.feature.x.enabled=true",
  "spring.datasource.url=jdbc:h2:mem:test"
})
class FeatureXTests { /* … */ }

// Or @SpringBootTest(properties = {...})

9. Using Test Slices

Slice Loads
@WebMvcTest MVC infrastructure + controller
@WebFluxTest WebFlux infrastructure
@DataJpaTest JPA + embedded DB + transactions
@DataR2dbcTest R2DBC reactive
@DataMongoTest MongoDB
@DataRedisTest Redis
@JsonTest Jackson/Gson serializers
@RestClientTest RestClient + MockRestServiceServer
@JdbcTest JDBC + embedded DB

10. Testing Security with @WithMockUser

Example: Security test with mock user and JWT

@Test
@WithMockUser(username="alice", roles={"ADMIN"})
void adminOnly() throws Exception { /* … */ }

@Test
@WithAnonymousUser
void requiresAuth() throws Exception { /* … */ }

@Test
void jwt() throws Exception {
  mvc.perform(get("/api/me").with(jwt().jwt(j -> j.subject("123"))));
}

11. Writing Unit Tests with JUnit 5 and Mockito

Example: Unit test with Mockito mocks

@ExtendWith(MockitoExtension.class)
class OrderServiceTests {
  @Mock OrderRepository repo;
  @Mock PaymentClient pay;
  @InjectMocks OrderService service;

  @Test void placesOrder() {
    when(repo.save(any())).thenAnswer(a -> a.getArgument(0));
    Order o = service.place(new NewOrder(/* … */));
    verify(pay).charge(any());
    assertNotNull(o);
  }
}

12. Using Testcontainers for Integration Tests

Example: Testcontainers with dynamic properties

@SpringBootTest
@Testcontainers
class PostgresIT {
  @Container static PostgreSQLContainer<?> pg = new PostgreSQLContainer<>("postgres:16");
  @DynamicPropertySource
  static void props(DynamicPropertyRegistry r) {
    r.add("spring.datasource.url", pg::getJdbcUrl);
    r.add("spring.datasource.username", pg::getUsername);
    r.add("spring.datasource.password", pg::getPassword);
  }
}
// Or @ServiceConnection (Boot 3.1+)

13. Testing Async Methods and Events

Tool Use
Awaitility Poll for async condition
@RecordApplicationEvents Capture published events
CountDownLatch Synchronize listener completion
Sync executor in tests SyncTaskExecutor bean override