Reputation: 93
I try to mock a mvc request for testing end to end my controller in spring.
The post request needs a request body but I get an error 400 telling me that required request body is missing even though I see its body using MockMvcResultsHandler print.
project architecture :
So here's my application.properties
spring.datasource.url=jdbc:h2:mem:tesdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=*****
spring.datasource.password=*****
spring.jpa.show-sql = true
Here's my test
@SpringBootTest
@AutoConfigureMockMvc
public class IntegrationTest {
protected User mockUser;
protected List<User> allUsers;
@Autowired
private MockMvc mvc;
@Autowired
private WebApplicationContext webApplicationContext;
@BeforeEach
public void setUp() {
this.mvc = MockMvcBuilders.webAppContextSetup(this.webApplicationContext).build();
}
@Test
void testGetAllUsers() throws Exception {
this.mvc.perform(post("/api/users")
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.characterEncoding("utf-8")
.content("{\"name\":\"name\"}"))
.andDo(print())
.andExpect(status().isCreated());
}
}
My @RestController
@PostMapping(path = "/users")
public @ResponseBody ResponseEntity<User> addNewUser(
@RequestBody String name
) {
return userService.createUser(name);
}
and my user @Service
public ResponseEntity<User> createUser(String name) {
User user = new User();
user.setName(name);
userRepository.save(user);
And when I try to launch my test I get in my debug console
DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing: public org.springframework.http.ResponseEntity<java.lang.String> ....addNewType(java.lang.String,java.lang.Boolean)]
MockHttpServletRequest:
HTTP Method = POST
Request URI = /api/users
Parameters = {}
Headers = [Content-Type:"application/json;charset=utf-8", Accept:"application/json", Content-Length:"32"]
Body = {"name":"concat"}
Session Attrs = {}
and response is :
MockHttpServletResponse:
Status = 400
Error message = null
Headers = []
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
get methods seems to work when I use the same architecture, body seems to be present in the console but servelt doesn't seem to see/understand the request body.
Upvotes: 0
Views: 5496
Reputation: 165
Try to add double quotes (") on the string you are sending in content:
mvc.perform(post("/url")
.content("\"myName\"")
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk());
Because you need to send a simple String that's the argument:
public @ResponseBody ResponseEntity<User> addNewUser(
@RequestBody String name){
....
}
If you need to send:
.content("{\"name\":\"name\"}"))
Then you would need a dto (for example UserDto with a property "name") as an argument of addNewUser method.
Upvotes: -1
Reputation: 93
So this was a simplified example of my real web service. Problem came from the fact that I used several time @RequestBody in the same request
public @ResponseBody ResponseEntity<User> addNewUser(
@RequestBody String name ,
@RequestBody String lastName,
which was the source of the problem.
To solve that I created a DTO like
public @ResponseBody ResponseEntity<User> addNewUser(
@RequestBody UserDTO userDto
And now it is working fine
Upvotes: 1
Reputation: 9
Try Creating a explicit json and then pass in body, also in your controller, you are expecting a single string name, try getting that from the json. eg:
@Test
void testGetAllUsers() throws Exception {
JSONObject json = new JSONObject();
json.put("name", "john");
this.mvc.perform(post("/api/users")
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.characterEncoding("utf-8")
.content(json.toString())
.andDo(print())
.andExpect(status().isCreated()); }
And in your controller you can try something like this
@PostMapping(path = "/users")
public @ResponseBody ResponseEntity<User> addNewUser(
@RequestBody String name
) {
JSONObject json = new JSONObject(name);
String userName = json.getString("name");
return userService.createUser(userName);
}
Upvotes: -1
Reputation: 166
Good Day!
Need to check:
Upvotes: -1