'Spring Controller testing with MockMvc post method
I am trying to test a method of my controller in a Spring Boot application. This is a post endpoint, which gets an id in a request and it passes on this id to a service:
@Slf4j
@Controller
public class AdministrationController {
private final AdministrationService administrationService;
@Autowired
public AdministrationController(AdministrationService administrationService) {
this.administrationService = administrationService;
}
@PostMapping("/administration")
public @ResponseBody ResponseEntity<String> deleteByMessageId(String id) {
return new ResponseEntity<>(administrationService.deleteMessageById(id), HttpStatus.OK);
}
}
The test for this method of the controller:
RunWith(SpringRunner.class)
@WebMvcTest(AdministrationController.class)
public class AdministrationControllerTest {
@Autowired
private MockMvc mvc;
@MockBean
private AdministrationService service;
@Test
public void
deleteByMessageId_whenCalled_thenServiceMethodIsCalledWithRequestParameters() throws Exception {
Object randomObj = new Object() {
public final String id = "1234";
};
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(randomObj);
MvcResult result = mvc.perform(
post("/administration")
.contentType(MediaType.APPLICATION_JSON)
.content(json))
.andExpect(status().isOk())
.andReturn();
verify(service, times(1)).deleteMessageById("1234");
}
}
When I run this test, the post request is executed, but with an empty body:
MockHttpServletRequest:
HTTP Method = POST
Request URI = /administration
Parameters = {}
Headers = {Content-Type=[application/json]}
Body = <no character encoding set>
Session Attrs = {}
It seems, even though I set the content in my test, it does not appear in the request I am sending. And, indeed, the test fails:
Argument(s) are different! Wanted: "1234"
Actual invocation has different arguments: null
What am I missing here? How can I set the request body with MockMvc?
Solution 1:[1]
Try to use .characterEncoding("utf-8")) :
MvcResult result = mvc.perform(post("/administration")
.contentType(MediaType.APPLICATION_JSON)
.content(json)
.characterEncoding("utf-8"))
.andExpect(status().isOk())
.andReturn();
Solution 2:[2]
Another option (that is inspired by @stelios-anastasakis answer) is to provide character encoding within the Content-Type header:
MvcResult result = mvc.perform(post("/administration")
.contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)
.content(json)
.andExpect(status().isOk())
.andReturn();
Note that we use MediaType.APPLICATION_JSON_UTF8_VALUE instead of MediaType.APPLICATION_JSON here.
Solution 3:[3]
mockMvc.perform(post( "/request")
.content(objectMapper.writeValueAsString(requestBody))
.contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
.andDo(print())
.andExpect(status().isOk());
Solution 4:[4]
You are surely missing the annotation for your method's parameter.
public @ResponseBody ResponseEntity<String> deleteByMessageId(String id)
Should be something like:
public @ResponseBody ResponseEntity<String> deleteByMessageId(@RequestParam("id") String id)
If you want to use it as a request parameter.
Take a look at the Spring MVC documentation here. Of course writing the test depends on how you expect the id here.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | stelios.anastasakis |
| Solution 2 | Slava Semushin |
| Solution 3 | Rawan AlKhalawi |
| Solution 4 | Arnold Galovics |
