Simple Spring Boot: POST

A very quick and little tutorial into sending a POST request to a Rest Controller in Spring Boot.

Have a look at Spring’s starter guide if your starting from scratch. The setup that is not described in this post is covered there.

The Maven dependencies required in this post are

The Rest Controller

The first thing to notice is that the class is annotated with @RestController allowing it to accept the requests that are sent to its path, which is “/” as one has not been defined in this example. Some beans have been injected in using the @Autowired annotation allowing them to be used in this controller.

Onto the more POST specific code. @RequestMapping defines the path that the annotated method can accept requests from and specifies that this method accepts POST requests.

This method accepts requests from

the rest of the request .../persistPerson

For example

localhost:8080/persistPerson

By default if no method is mentioned then it will accept GET requests. @RequestBody marks that the person input is retrieved from the body / content of the POST request. This is a notable difference between GET and POST as the GET request does contain a body.

As POST requests are meant to be used to save new data to a database this example does just that, although none of the actual persistence code is actually implemented. If the input person is valid then it will call the repositories persist method and return a HttpStatus.CREATED (201) response code. This is the response code that is normally returned from a successful POST request. If the person was not valid then it returns a different response code. I used I_AM_A_TEAPOT (418) as it looked silly but it should probably be NO_CONTENT (204) or CONFLICT (409) although I there does not seem to be a consensus on what the correct response is.

To manually test this I used Postman. To send a POST request to the Rest Controller:

  • Set the request type to POST
  • Set the content type in the header to application/json; charset=UTF-8
  • Add the JSON for the PersonDTO to the body of the request (in the raw option)
  • Add the request path
  • Press send

If you haven’t already, startup your server before you try to send the request or obviously it wont wont.

Request path

localhost:8080/persistPerson

Body

{
 "firstName": "First name",
 "secondName": "Second name",
 "dateOfBirth": "01/12/2020",
 "profession": "Software Developer",
 "salary": 0
}

These two pictures below should help make this clearer

Postman-Post-Example-1

Postman-Post-Example-2.PNG

It’s probably also a good idea to test the code. So lets look at how to do so.

The @WebMvcTest annotation is used which will disable full auto-configuration and only apply configuration relevant to MVC tests including setting up the MockMvc used in this test. The PersonRestController has been marked in the annotation as it is the test subject. Using MockMvc provides a faster way of testing MVC controllers like the PersonRestController as it removes the need to fully start a HTTP server. @MockBean is used on each bean that was injected into the PersonRestController so that they are then mocked in the tests.

Each test converts the personDTO into JSON using the JacksonTester and sends a POST request that includes the JSON in its body / content. The tests will pass if the correct response code is returned and if personRespository.persist was called the correct amount of times. Mockito is used to mock the return of the personService.isValid method and to verify if personRepository.persist was called or not.

By reaching this point you should be able write a simple Rest Controller that can accept POST requests and be able to manually test it with Postman and automatically with a test.

The code used in this post can be found on my GitHub.

 

  1. This looks great! The only question I have is: if I were to make use of JPA in my application, would there be a way to avoid the need of making the test an integration test using @SpringBootTest?

    I would like to just test a Controller class (annotated with @RestController) without the Repositories and Services (I would test those otherwise). So in your example: imagine PersonDTO is an entity, which has JPA annotations stating how an instance of this class was to be saved in a database. What would be necessary to make the test work in a similar fashion to the test you showed here?

    Like

    Reply

    1. It’s been a while with this one so I could be wrong, but from looking at the test class it looks like it should still work for your use case. Using the @MockBean annotation on your repository and mocking it like its done in the example. Call verify to check that a call to the repository occurred and when to mock an output of any repository methods that you need (both from Mockito). The PersonDTO could be straight up swapped for an entity or have entity annotations added and the test should still work the same due to mocking out the repository.

      Like

      Reply

  2. Thanks for writting this! You made it really complete by adding the tests. I’ve tried getting around the conversion to json, but I haven’t succeeded. Would you know how to do this? Or whether it may be (im)possible at all? I’m kinda bummed that my Controller takes a POJO as an argument, but I still have to convert to json (as a String) in the test. Thanks in advance!

    Like

    Reply

    1. I think you don’t have any other options unless you want to do more of a unit test and skip out the sending of the JSON input all together. As far as I’m aware a request is sent via mockMvc and the controller is expecting a JSON body so there’s not much you can do.

      Hopefully that is correct, I would need to search myself to answer that concretely.

      Thanks
      Dan

      Like

      Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s

%d bloggers like this: