title: How can I use @WebMvcTest for Unit Test POST method?
body: <p>I'm running unit tests with Spring Boot and Mockito and I'm testing RESTful services. When I try to test the GET method it works successfully but when I try to test the POST method it fails. What should I do to resolve this problem? Thanks in advance!</p>
  
  <p>This is the code for the REST Controller:</p>
  
  <pre><code>package com.dgs.restfultesting.controller;
  
  import java.net.URI;
  import java.util.List;
  
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.http.ResponseEntity;
  import org.springframework.web.bind.annotation.GetMapping;
  import org.springframework.web.bind.annotation.PostMapping;
  import org.springframework.web.bind.annotation.RequestBody;
  import org.springframework.web.bind.annotation.RestController;
  import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
  
  import com.dgs.restfultesting.business.ItemBusinessService;
  import com.dgs.restfultesting.model.Item;
  
  @RestController
  public class ItemController {
  
      @Autowired
      private ItemBusinessService businessService;
  
      @GetMapping("/all-items-from-database")
      public List&lt;Item&gt; retrieveAllItems() {
          return businessService.retrieveAllItems(); 
      }
  
      @PostMapping("/items")
      public Item addItem(@RequestBody Item item) {
          Item savedItem = businessService.addAnItem(item); 
  
          return savedItem;
      }
  }
  </code></pre>
  
  <p>Business Layer:</p>
  
  <pre><code>package com.dgs.restfultesting.business;
  
  import java.util.List;
  
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.stereotype.Component;
  
  import com.dgs.restfultesting.data.ItemRepository;
  import com.dgs.restfultesting.model.Item;
  
  @Component
  public class ItemBusinessService {
  
      @Autowired
      private ItemRepository repository;
  
      public Item retrieveHardcodedItem() {
          return new Item(1, "Book", 10, 100); 
      }
  
      public List&lt;Item&gt; retrieveAllItems() {
  
          List&lt;Item&gt; items = repository.findAll(); 
  
          for (Item item : items) {
              item.setValue(item.getPrice() * item.getQuantity());  
          }
  
          return items;  
      }
  
      public Item addAnItem(Item item) {
          return repository.save(item); 
      }
  }
  </code></pre>
  
  <p>ItemControllerTest:</p>
  
  <pre><code>package com.dgs.restfultesting.controller;
  
  import static org.hamcrest.CoreMatchers.containsString;
  import static org.junit.Assert.assertEquals;
  import static org.mockito.Mockito.when;
  import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
  
  import java.util.Arrays;
  
  import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
  import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
  
  import org.junit.Test;
  import org.junit.runner.RunWith;
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
  import org.springframework.boot.test.mock.mockito.MockBean;
  import org.springframework.http.MediaType;
  import org.springframework.test.context.junit4.SpringRunner;
  import org.springframework.test.web.servlet.MockMvc;
  import org.springframework.test.web.servlet.MvcResult;
  import org.springframework.test.web.servlet.RequestBuilder;
  import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
  
  import com.dgs.restfultesting.business.ItemBusinessService;
  import com.dgs.restfultesting.model.Item;
  
  @RunWith(SpringRunner.class)             
  @WebMvcTest(ItemController.class)  
  public class ItemControllerTest {
  
      @Autowired
      private MockMvc mockMvc;    
  
      @MockBean
      private ItemBusinessService businessService;
  
      @Test
      public void retrieveAllItems_basic() throws Exception {
  
          when(businessService.retrieveAllItems()).thenReturn(
                  Arrays.asList(new Item(2, "iPhone", 1000, 10),
                          new Item(3, "Huawei", 500, 17)));
  
          RequestBuilder request = MockMvcRequestBuilders
                  .get("/all-items-from-database") 
                  .accept(MediaType.APPLICATION_JSON); 
  
          MvcResult result = mockMvc.perform(request)
                  .andExpect(status().isOk())
                  .andExpect(content().json("[{id:2, name:iPhone, price:1000}, {id:3, name:Huawei, price:500}]"))  // This will return an array back, so this data should be within an array
                  .andReturn();  
      }   
  
      @Test
      public void createItem() throws Exception {
          RequestBuilder request = MockMvcRequestBuilders
                  .post("/items")
                  .accept(MediaType.APPLICATION_JSON)
                  .content("{\"id\":1,\"name\":\"Book\",\"price\":10,\"quantity\":100}")
                  .contentType(MediaType.APPLICATION_JSON);
  
          MvcResult result = mockMvc.perform(request)
                  .andExpect(status().isCreated())
                  .andExpect(header().string("location", containsString("/item/")))
                  .andReturn();
      }
  }
  </code></pre>
  
  <p>There is no problem to test the retrieveAllItems_basic() method, but when I try to run a JUnit test for createItem() method, it doesn't work and I get this: java.lang.AssertionError: Status expected:&lt;201> but was:&lt;200></p>
  
  <p>And this is what I receive in the Console:</p>
  
  <pre><code>MockHttpServletRequest:
        HTTP Method = POST
        Request URI = /items
         Parameters = {}
            Headers = {Content-Type=[application/json], Accept=[application/json]}
               Body = &lt;no character encoding set&gt;
      Session Attrs = {}
  
  Handler:
               Type = com.dgs.restfultesting.controller.ItemController
             Method = public com.dgs.restfultesting.model.Item com.dgs.restfultesting.controller.ItemController.addItem(com.dgs.restfultesting.model.Item)
  
  Async:
      Async started = false
       Async result = null
  
  Resolved Exception:
               Type = null
  
  ModelAndView:
          View name = null
               View = null
              Model = null
  
  FlashMap:
         Attributes = null
  
  MockHttpServletResponse:
             Status = 200
      Error message = null
            Headers = {}
       Content type = null
               Body = 
      Forwarded URL = null
     Redirected URL = null
            Cookies = []
  2018-10-07 17:53:51.457  INFO 55300 --- [       Thread-3] o.s.w.c.s.GenericWebApplicationContext   : Closing org.springframework.web.context.support.GenericWebApplicationContext@71075444: startup date [Sun Oct 07 17:53:48 EEST 2018]; root of context hierarchy
  </code></pre>
  
  <p><strong>Update -----------------------------</strong></p>
  
  <p>I try to set the location like this: item/id.</p>
  
  <p>This is the code for the controller:</p>
  
  <pre><code>@PostMapping("/items")
  public ResponseEntity&lt;Object&gt; addItem(@RequestBody Item item) {
      Item savedItem = businessService.addAnItem(item); 
      HttpHeaders httpHeaders = new HttpHeaders();
      UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.newInstance();
  
      UriComponents uriComponents =
              uriComponentsBuilder.path("/item/{id}").buildAndExpand(savedItem.getId());
      httpHeaders.setLocation(uriComponents.toUri());
  
      return new ResponseEntity&lt;&gt;(savedItem, httpHeaders, HttpStatus.CREATED); 
  }
  </code></pre>
  
  <p>This is the code for test:</p>
  
  <pre><code>@Test
  public void createItem() throws Exception {
  
      RequestBuilder request = MockMvcRequestBuilders
              .post("/items")
              .accept(MediaType.APPLICATION_JSON)
              .content("{\"id\":1,\"name\":\"Book\",\"price\":10,\"quantity\":100}")
              .contentType(MediaType.APPLICATION_JSON);
  
      MvcResult result = mockMvc.perform(request)
              .andExpect(status().isCreated())
              .andExpect(header().string("location", containsString("/item/1")))
              .andReturn();
  }
  </code></pre>
  
  <p>When I run the JUnit test for createItem() method I get this error: org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException</p>