If you're stumped about how to deal with a 415 response code from your Spring Boot unit tests, you've come to the right place.

In this very brief article, I'll show you how to overcome it.

TL;DR

You gotta set the Content-Type header, Hoss. 

If you're unsure how to do that, read on.

A Simple Controller

Consider this very rudimentary controller:

@RestController
@RequestMapping("/contact")
public class ContactsController {
    
    private static final Logger LOG = LoggerFactory.getLogger(ContactsController.class);
            
    
    @PostMapping("")
    public ResponseEntity<?> createContact(@Validated(Contact.StepOne.class) @RequestBody Contact contact) {
        LOG.debug("Creating new contact: " + contact);
        return ResponseEntity.status(HttpStatus.CREATED).body(contact);
    }    
}

The purpose of the controller is that it simulates the logic behind creating a contact in a CRM application. 

The single method accepts a POST request to the /contact endpoint. It also accepts a payload with properties that map to the Contact class.

The method handles group-level validation with the @Validated annotation.

At the end of the day, it returns the object that got created. No big deal.

Here's a typical request and response as seen through the eyes of Postman:

 

So it all works as expected.

But the question is: if that works, then why don't your MockMvc unit tests?

A Simple Test

Consider this unit test:

    @Test
    public void testCreateContactWithGoodData() throws Exception {
        this.mockMvc
            .perform(MockMvcRequestBuilders.post("/contact")
            .content("{\"firstName\" : \"Johnny\", \"lastName\" : \"Doe\"}"))
            .andDo(MockMvcResultHandlers.print())
            .andExpect(MockMvcResultMatchers.status().is(HttpStatus.CREATED.value()))
            .andExpect(MockMvcResultMatchers.jsonPath("$.firstName").value("Johnny"));
    }

It's using MockMvc to handle web layer testing. You might think by looking at it that it will sail through with flying colors.

But not so fast. When you run that test, you see this:

 

Aaaarrrgghhh!

So what happened?

What Is That 415 Error?

An HTTP response code of 415 means "Unsupported Media Type." In other words, the Spring Boot application rejected the request because it didn't understand the format.

That's because you didn't specify a format via the Content-Type header. You need to do that.

Just update the code above to look like this:

    @Test
    public void testCreateContactWithGoodData() throws Exception {
        this.mockMvc
            .perform(MockMvcRequestBuilders.post("/contact")
            .contentType(MediaType.APPLICATION_JSON)
            .content("{\"firstName\" : \"Johnny\", \"lastName\" : \"Doe\"}"))
            .andDo(MockMvcResultHandlers.print())
            .andExpect(MockMvcResultMatchers.status().is(HttpStatus.CREATED.value()))
            .andExpect(MockMvcResultMatchers.jsonPath("$.firstName").value("Johnny"));
    }

Pay close attention to that .contentType() method above. That's what makes all the difference.

Now run your test again with the addition of that line and watch it light up green.

 

If you're wondering why you didn't see the error with Postman, it's probably because you set the content type to JSON in the Body tab.

Wrapping It Up

That should do it. I'll keep this one short and sweet.

You can see the whole source code for the snippets above on GitHub.

Have fun!

Photo by freestocks.org from Pexels