CodeGym /Courses /Module 5. Spring /Lecture 264: Integration testing of microservices with Mo...

Lecture 264: Integration testing of microservices with MockMvc

Module 5. Spring
Level 21 , Lesson 3
Available

Imagine we're building a microservice responsible for processing orders in an online store. It handles HTTP requests, calls services to check product availability in the warehouse, interacts with the database to persist order info. All of this is a set of interacting components. And even if you've tested them individually with unit tests, that doesn't guarantee everything works together correctly. That's exactly where integration testing comes into play.

Integration testing at the microservice level lets you:

  • Verify the interaction between controllers, services, repositories and other components.
  • Make sure the whole microservice functions correctly without depending on real external dependencies.
  • Emulate real HTTP requests and check how the app handles them and returns responses.

MockMvc: the key tool for integration testing

Before we dive into testing, let's break down what MockMvc is.

MockMvc is a handy tool from Spring Test that lets you:

  • Mock HTTP requests to your application without starting a real web server.
  • Check how your controller handles requests, returns responses, and works with internal services.
  • Simulate real API scenarios, including sending parameters, request bodies, custom headers, and more.

Think about it like this: instead of assembling the whole car and driving it on a test track, you test just the engine, but under load close to real conditions. In simple terms: MockMvc lets you test the web layer of your application in isolation, without the need to spin up the entire server.

Why MockMvc is better for integration tests?

MockMvc gives you an easy way to test:

  • Faster than running full integration tests that start the server. This saves time, especially in big projects.
  • Isolates the layer under test. If the database or other external systems aren't ready, tests won't be blocked because you can mock them.
  • Flexible API. MockMvc makes it easy to send requests and verify how your controllers handle them.

Getting ready to work with MockMvc

Before we jump into examples, make sure your project is set up for testing.

First let's make sure your pom.xml (or build.gradle) includes the test dependencies:


<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

To work with MockMvc you'll need the following setup in your test class:


@SpringBootTest // Starts the Spring context for tests
@AutoConfigureMockMvc // Enables automatic MockMvc configuration

Easy, right? Now your test class is ready to go.


Practice: Testing a REST API with MockMvc

Enough theory — let's show how this works in practice!

Assume we have a microservice for managing books, with a REST API that works with a collection of books.

Controller for testing

Here's an example controller that provides HTTP methods for working with books:


@RestController
@RequestMapping("/books")
public class BookController {

    private final BookService bookService;

    public BookController(BookService bookService) {
        this.bookService = bookService;
    }

    @GetMapping("/{id}")
    public ResponseEntity<Book> getBook(@PathVariable Long id) {
        return ResponseEntity.ok(bookService.findBookById(id));
    }

    @PostMapping
    public ResponseEntity<Book> createBook(@RequestBody Book book) {
        return ResponseEntity.status(HttpStatus.CREATED).body(bookService.saveBook(book));
    }
}

We have two endpoints:

  1. GET /books/{id} — returns a book by its identifier.
  2. POST /books — adds a new book.

Writing controller tests with MockMvc

Now let's write tests for this controller. First, create a test class:


@SpringBootTest
@AutoConfigureMockMvc
class BookControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private BookService bookService; // Mocking the service dependency

    @Test
    void testGetBook() throws Exception {
        // Test data
        Book book = new Book(1L, "The Hobbit", "J.R.R. Tolkien");
        Mockito.when(bookService.findBookById(1L)).thenReturn(book);

        // Send GET request and verify the result
        mockMvc.perform(get("/books/1"))
                .andExpect(status().isOk()) // Expect 200 OK status
                .andExpect(jsonPath("$.title").value("The Hobbit")) // Check the title field
                .andExpect(jsonPath("$.author").value("J.R.R. Tolkien")); // Check the author field
    }

    @Test
    void testCreateBook() throws Exception {
        // Test data
        Book book = new Book(null, "1984", "George Orwell");
        Book savedBook = new Book(2L, "1984", "George Orwell");

        Mockito.when(bookService.saveBook(Mockito.any())).thenReturn(savedBook);

        // Send POST request with JSON payload
        String bookJson = """
                {
                  "title": "1984",
                  "author": "George Orwell"
                }
                """;

        mockMvc.perform(post("/books")
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(bookJson))
                .andExpect(status().isCreated()) // Expect 201 Created status
                .andExpect(jsonPath("$.id").value(2L)) // Verify that book ID = 2
                .andExpect(jsonPath("$.title").value("1984")) // Verify title
                .andExpect(jsonPath("$.author").value("George Orwell")); // Verify author
    }
}

What's happening here?

  1. Annotations:
    • @SpringBootTest brings up the full Spring context.
    • @AutoConfigureMockMvc configures MockMvc automatically.
    • @MockBean creates a mock for the BookService dependency that we use to isolate the controller.
  2. The tests:
    • In testGetBook we mock the findBookById method in the service to return a Book object. Then we send a GET request and verify the response contains the correct data.
    • In testCreateBook we mock the saveBook method, send a POST request with JSON payload and verify the response contains the created book data.
  3. MockMvc API:
    • mockMvc.perform(...) executes the HTTP request.
    • andExpect(...) holds all assertions on the result, from the response status to the JSON content.

Common mistakes when using MockMvc

So, what should you watch out for:

  • MockMvc or @AutoConfigureMockMvc not declared. In that case tests won't be able to use MockMvc.
  • JSON serialization errors. Check if Jackson is included in your project.
  • Missing mocks for dependencies. MockMvc tests only the controller layer, so be sure to mock services via @MockBean.

MockMvc is an incredibly powerful tool for testing interactions with your controllers. It lets you test HTTP requests on the fly and spot issues that might only show up in real usage. With it you can be confident your API behaves correctly even before you deploy to production.

Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION