Backend Development 14 min read

Master Spring Boot Testing: Real‑World Cases and Advanced Techniques

This article provides a comprehensive guide to Spring Boot testing, covering core utilities, essential annotations, dependency libraries, web environment configurations, and practical code examples for unit, slice, and integration tests across JUnit, MockMvc, TestRestTemplate, JPA, Redis, and REST client scenarios.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Master Spring Boot Testing: Real‑World Cases and Advanced Techniques

1. Introduction

Spring Boot offers a rich set of testing utilities and annotations that simplify testing of applications. The testing support is provided by two modules: spring-boot-test (core features) and spring-boot-test-autoconfigure (automatic configuration for tests).

Spring Boot Test integrates with Spring Test and enhances mock capabilities, supporting unit tests, slice tests, and full‑stack functional tests.

2. Core Annotations and Dependencies

Key annotations include:

@Test – marks a unit test method.

@WebMvcTest – slice test for Spring MVC controllers.

@DataJpaTest – slice test for JPA repositories.

@SpringBootTest – full‑stack integration test.

The spring-boot-starter-test dependency brings the following libraries:

JUnit 5 – standard unit testing framework for Java.

Spring Test & Spring Boot Test – utilities for testing Spring Boot applications.

AssertJ – fluent assertion library.

Hamcrest – matcher library.

Mockito – mocking framework.

JSONassert – JSON assertion library.

JsonPath – JSON XPath support.

3. Web Environment Options

The @SpringBootTest annotation can customize the web environment via the webEnvironment attribute:

MOCK (default) – loads a mock web environment without starting an embedded server.

RANDOM_PORT – starts an embedded server on a random port.

DEFINED_PORT – starts an embedded server on a configured or default port (8080).

NONE – loads the application context without any web environment.

3.1 Reactive Web Type

<code>@SpringBootTest(properties = "spring.main.web-application-type=reactive")
public class SpringBootTest01 {}
</code>

This configuration declares a reactive WebFlux application.

3.2 Passing Application Arguments

<code>@SpringBootTest(args = "--app.test=Pack")
public class MailServiceTest {
  @Test
  public void testAppArgumentsPopulated(@Autowired ApplicationArguments args) {
    assertThat(args.getOptionNames()).containsOnly("app.test");
    assertThat(args.getOptionValues("app.test")).containsOnly("Pack");
  }
}
</code>

3.3 Mock Environment with MockMvc

<code>// Controller to be tested
@RestController
@RequestMapping("/demos")
public class DemoController {
  @GetMapping("/index")
  public Object index() { return "demo index"; }
}

// Unit test using MockMvc
@SpringBootTest
@AutoConfigureMockMvc
public class SpringBootTest02 {
  @Test
  public void testMockMvc(@Autowired MockMvc mvc) throws Exception {
    mvc.perform(get("/demos/index"))
       .andExpect(status().isOk())
       .andExpect(content().string("demo index1")); // intentional mismatch to show failure
  }
}
</code>

3.4 Running with Real Server (RANDOM_PORT)

<code>@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class SpringBootTest03 {
  @Test
  public void testRestTemplate(@Autowired TestRestTemplate restTemplate) throws Exception {
    String body = restTemplate.getForObject("/demos/index", String.class);
    assertThat(body).isEqualTo("123");
  }
}
</code>

3.5 Mocking Beans with @MockBean

<code>// Existing component
@Service
public class RemoteService {
  public String getValue() { return "RemoteData"; }
}

// Business component
@Service
public class BusinessService {
  @Resource private RemoteService remoteService;
  public String getReverseValue() {
    return new StringBuilder(this.remoteService.getValue()).reverse().toString();
  }
}

// Test class
@SpringBootTest
public class SpringBootTest04 {
  @Resource private BusinessService businessService;
  @MockBean private RemoteService remoteService;

  @Test
  public void exampleTest() {
    given(this.remoteService.getValue()).willReturn("pack");
    String reverse = this.businessService.getReverseValue();
    assertThat(reverse).isEqualTo("kcap1"); // intentional mismatch to illustrate output
  }
}
</code>

4. Slice Tests

4.1 @WebMvcTest

<code>@RestController
@RequestMapping("/business")
public class BusinessController {
  @Resource private RemoteService remoteService;
  @GetMapping("/info")
  public String info() { return this.remoteService.getValue(); }
}

@WebMvcTest(BusinessController.class)
public class SpringBootTest05 {
  @Autowired private MockMvc mvc;
  @MockBean private RemoteService remoteService;

  @Test
  public void testInfo() throws Exception {
    given(this.remoteService.getValue()).willReturn("pack1");
    mvc.perform(get("/business/info").accept(MediaType.TEXT_PLAIN))
       .andExpect(status().isOk())
       .andExpect(content().string("pack"));
  }
}
</code>

4.2 @DataJpaTest

<code>@DataJpaTest
@AutoConfigureTestDatabase(replace = Replace.NONE)
public class SpringBootTest06 {
  @Autowired private TestEntityManager entityManager;
  @Autowired private UserRepository repository;

  @Test
  public void testExample() {
    User entity = new User();
    entity.setAge(20);
    entity.setName("pack");
    this.entityManager.persist(entity);
    User user = this.repository.findById(100001).orElse(entity);
    assertThat(user.getName()).isEqualTo("pack1"); // intentional mismatch
  }
}
</code>

4.3 @DataRedisTest

<code>@DataRedisTest
public class SpringBootTest07 {
  @Resource private PersonRepository personRepository;
  // ... test logic ...
}
</code>

4.4 @RestClientTest

<code>@Service
public class RemoteService {
  @Resource private RestTemplate restTemplate;
  public String remote() {
    return this.restTemplate.getForObject("http://localhost:8088/demos/cf?ids=pack", String.class);
  }
}

@RestClientTest(RemoteService.class)
@AutoConfigureWebClient(registerRestTemplate = true)
public class SpringBootTest07 {
  @Resource private RemoteService service;
  @Resource private MockRestServiceServer server;

  @Test
  public void getInfo() {
    this.server.expect(requestTo("http://localhost:8088/demos/cf?ids=pack"))
        .andRespond(withSuccess("pack", MediaType.TEXT_PLAIN));
    String greeting = this.service.remote();
    assertThat(greeting).isEqualTo("pack");
  }
}
</code>

4.5 TestRestTemplate

<code>public class SpringBootTest08 {
  private final TestRestTemplate template = new TestRestTemplate();

  @Test
  public void testRequest() {
    ResponseEntity<String> response = this.template.getForEntity(
        "http://localhost:8088/demos/cf?ids=123pack", String.class);
    assertThat(response.getStatusCode().is2xxSuccessful());
    assertThat(response.getBody()).isEqualTo("pack");
  }
}
</code>
<code>@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class SpringBootTest09 {
  @Resource private TestRestTemplate template;

  @Test
  public void testRequest() {
    ResponseEntity<String> response = this.template.getForEntity(
        "http://localhost:8088/demos/cf?ids=123pack", String.class);
    assertThat(response.getStatusCode().is2xxSuccessful());
    assertThat(response.getBody()).isEqualTo("\"123pack\"");
  }

  @TestConfiguration(proxyBeanMethods = false)
  static class RestTemplateBuilderConfiguration {
    @Bean
    RestTemplateBuilder restTemplateBuilder() {
      return new RestTemplateBuilder()
          .setConnectTimeout(Duration.ofSeconds(1))
          .setReadTimeout(Duration.ofSeconds(1));
    }
  }
}
</code>

The article concludes with a reminder that all provided examples are part of a continuously updated Spring Boot testing collection, freely available to readers.

testingspring-bootmockmvcdatajpadataredisjunit5mockbeantestresttemplate
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.