CodeGym /Courses /Module 5. Spring /Lecture 265: Practice: testing REST API using MockMvc

Lecture 265: Practice: testing REST API using MockMvc

Module 5. Spring
Level 21 , Lesson 4
Available

When you're building a web app with Spring — you need to make sure it actually works. For that there's a great tool called MockMvc. Think of your app as a modern cafe. Normally, to test how it works you'd have to open the whole place: kitchen, dining room, seat the waiters. That's like starting a full server — slow and heavy. MockMvc is like making a mini version of the cafe with one cook and a pickup window. You can make orders through the window (send requests) and get dishes back (responses) without running the whole business. In Spring terms that means you can test your app in a lightweight mode — no full server or DB connection required.


Setting up the test environment

First, make sure you've added the necessary test dependencies. In your pom.xml (if you're using Maven) or build.gradle (if Gradle) you should have the dependencies for Spring Boot Starter Test:

Maven:


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

Gradle:


testImplementation 'org.springframework.boot:spring-boot-starter-test'

MockMvc is already bundled with Spring Boot Starter Test, so you don't need extra dependencies.


Simple REST API testing with MockMvc

Input data

Let's say we have a REST controller for managing Product entities:


@RestController
@RequestMapping("/api/products")
public class ProductController {

    @GetMapping("/{id}")
    public ResponseEntity<Product> getProductById(@PathVariable Long id) {
        // This is a simplified stub. In real life there would be a call to a service.
        if (id == 1L) {
            return ResponseEntity.ok(new Product(1L, "Coffee", 5.0));
        }
        return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
    }
}

And we have the Product entity:


public class Product {
    private Long id;
    private String name;
    private Double price;

    // Constructors, getters and setters.
    public Product(Long id, String name, Double price) {
        this.id = id;
        this.name = name;
        this.price = price;
    }

    // Getters and setters
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }
}

Writing tests

Now let's write tests for ProductController. We want to make sure that:

  1. If we request a resource with an existing ID, we get the correct result.
  2. If a resource with the given ID doesn't exist, the API returns a 404.

public class Product {
    private Long id;
    private String name;
    private Double price;

    // Constructors, getters and setters.
    public Product(Long id, String name, Double price) {
        this.id = id;
        this.name = name;
        this.price = price;
    }

    // Getters and setters
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }
}
  1. The @WebMvcTest annotation: indicates we're testing only the controller layer. Spring will spin up the minimal required context.
  2. The mockMvc.perform() method: simulates an HTTP request. Here we specify the path (/api/products/1) and the method (GET).
  3. The andExpect() methods: help verify that the app returns the expected response. You can check:
    • Response status (isOk(), isNotFound(), etc.).
    • Content type (contentType()).
    • JSON response contents (jsonPath()).

Testing POST requests

Now add a method to our controller to create a product:

@PostMapping
public ResponseEntity<Product> createProduct(@RequestBody Product product) {
    product.setId(2L); // Stub: always return the same ID
    return ResponseEntity.status(HttpStatus.CREATED).body(product);
}

Let's write a test for this method. We want to make sure that:

  1. A POST request with valid data creates a product and returns status 201 (Created).
  2. The response body contains the created product.

@Test
public void testCreateProduct() throws Exception {
    String newProductJson = """
        {
            "name": "Tea",
            "price": 3.5
        }
    """;

    mockMvc.perform(post("/api/products") // Emulate a POST request
            .contentType(MediaType.APPLICATION_JSON) // Specify that the request body is JSON
            .content(newProductJson)) // Send the JSON data
            .andExpect(status().isCreated()) // Expect status 201 Created
            .andExpect(content().contentType(MediaType.APPLICATION_JSON)) // Response is JSON too
            .andExpect(jsonPath("$.id").value(2)) // Check ID
            .andExpect(jsonPath("$.name").value("Tea")) // Check product name
            .andExpect(jsonPath("$.price").value(3.5)); // Check product price
}

Common mistakes and caveats

  1. Error "No qualifying bean of type '...' found"
    When using @WebMvcTest only controllers are started in the test context. If your controller depends on services or other components, don't forget to mock them with Mockito:
    @MockBean
    private ProductService productService;
    
  2. Incorrect use of @Autowired
    Always use the right annotations (@Autowired or @MockBean) for wiring dependencies.
  3. JSON format in requests
    Make sure the JSON data you send in tests is valid. Use contentType(MediaType.APPLICATION_JSON).
  4. Issues with jsonPath
    It's a good idea to use online JSONPath validators to ensure your path expressions are correct.

At this point you've learned how to test REST APIs with MockMvc. These skills will help you catch bugs early and give you confidence in interviews where you might be asked to demo working with MockMvc.

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