Java > Testing in Java > Integration Testing > Spring Boot Test

Spring Boot Integration Test with TestRestTemplate

This snippet demonstrates a Spring Boot integration test using TestRestTemplate to test a REST endpoint. Integration tests verify that different parts of your application work correctly together. This example tests a simple controller that returns a greeting.

Project Setup

First, ensure you have a Spring Boot project set up with a basic REST controller. Include the spring-boot-starter-web and spring-boot-starter-test dependencies in your pom.xml or build.gradle file. The spring-boot-starter-test dependency provides testing utilities, including TestRestTemplate.

Example Controller

This is a simple REST controller with a single endpoint, /greeting, that accepts a name parameter and returns a greeting.

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class GreetingController {

    @GetMapping("/greeting")
    public String greeting(@RequestParam(value = "name", defaultValue = "World") String name) {
        return "Hello, " + name + "!";
    }
}

Integration Test

This integration test uses @SpringBootTest to start the Spring Boot application with a random port. TestRestTemplate is autowired to make HTTP requests to the running application. The tests verify that the /greeting endpoint returns the expected response with both the default and custom names.

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import static org.junit.jupiter.api.Assertions.assertEquals;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class GreetingControllerIntegrationTest {

    @LocalServerPort
    private int port;

    @Autowired
    private TestRestTemplate restTemplate;

    @Test
    public void greetingShouldReturnDefaultMessage() {
        ResponseEntity<String> response = restTemplate.getForEntity("http://localhost:" + port + "/greeting", String.class);
        assertEquals(HttpStatus.OK, response.getStatusCode());
        assertEquals("Hello, World!", response.getBody());
    }

    @Test
    public void greetingShouldReturnCustomMessage() {
        ResponseEntity<String> response = restTemplate.getForEntity("http://localhost:" + port + "/greeting?name=Test", String.class);
        assertEquals(HttpStatus.OK, response.getStatusCode());
        assertEquals("Hello, Test!", response.getBody());
    }
}

Concepts Behind the Snippet

This snippet showcases integration testing in Spring Boot, which involves testing the interaction between different components of the application. It verifies that the controller handles requests correctly and returns the expected responses. Key concepts include using @SpringBootTest to start the application context, TestRestTemplate to make HTTP requests, and assertions to validate the responses.

Real-Life Use Case Section

In a real-world application, you might use integration tests to verify the interaction between your controllers, services, and data repositories. For example, you could test that a controller correctly saves data to a database via a service. This ensures that all the layers of your application work together as expected.

Best Practices

  • Use a separate test configuration if needed to mock external dependencies.
  • Keep integration tests focused on verifying the interaction between components.
  • Use meaningful assertions to clearly identify failures.
  • Use random ports to avoid port conflicts during testing.

Interview Tip

When discussing integration testing in Spring Boot, be prepared to explain the difference between unit and integration tests. Unit tests focus on individual components in isolation, while integration tests verify the interaction between multiple components.

When to use them

Integration tests are best used when you want to verify that different parts of your application work together correctly. This is particularly useful for testing complex interactions between controllers, services, and databases. They help catch issues that might not be apparent during unit testing.

Memory footprint

Integration tests generally have a larger memory footprint than unit tests because they start the Spring Boot application context. However, the memory usage is usually manageable, especially when tests are properly scoped and configured.

Alternatives

Alternatives to TestRestTemplate include using WebTestClient (for reactive applications) or mocking the underlying components to perform more isolated tests. Also consider using tools like Selenium for end-to-end testing.

Pros

  • Verifies the interaction between multiple components.
  • Provides confidence that the application works as expected.
  • Helps catch integration-related issues early.

Cons

  • Can be slower to run than unit tests.
  • Requires more setup and configuration.
  • May be more difficult to debug.

FAQ

  • What is the difference between @SpringBootTest and @WebMvcTest?

    @SpringBootTest loads the complete Spring Boot application context, while @WebMvcTest only loads the web layer components (controllers, filters, etc.). @WebMvcTest is faster but does not test the entire application context. Using @SpringBootTest with webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT starts the application on a random port and enables full integration testing.
  • How do I mock external services in an integration test?

    You can use libraries like Mockito to mock external services or create a test configuration with mock beans to replace the actual service implementations. For example, create a @Configuration class annotated with @TestConfiguration and provide mock implementations of your services.