I am trying to write integration tests for my REST API implemented with Spring MVC.
Here is my REST implementation:
import org.myproject.api.input.ProjectInput;
import org.myproject.dao.ProjectsDao;
import org.myproject.model.Project;
import org.myproject.model.Projects;
import org.myproject.util.Exceptions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/projects")
public class ProjectsApi {
@Autowired
private ProjectsDao projectsDao;
...
@RequestMapping(value = "/",
method = RequestMethod.POST,
produces = {"application/json"},
consumes = {"application/json"})
public @ResponseBody Project addProject(@RequestBody ProjectInput projectInput) throws IOException {
logger.info("Add project");
Project project = projectInput.createProject();
projectsDao.add(project);
return project;
}
}
Here is ProjectInput class:
@XmlRootElement
public class ProjectInput {
private String name;
private String description;
// Constructor to make JSON converter happy
private ProjectInput() {}
public ProjectInput(String name, String description) {
this.name = name;
this.description = description;
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public void setName(String name) {
this.name = name;
}
public void setDescription(String description) {
this.description = description;
}
}
And here is my test:
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.openboard.api.input.ProjectInput;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations={"classpath*:applicationContext.xml"})
public class TestProjectsApi {
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
@Test
public void testAddProject() throws Exception {
ProjectInput input = new ProjectInput("name", "description");
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(input);
// json value is: {"name":"name","description":"description"}
mockMvc.perform(post("/projects/")
.contentType(MediaType.APPLICATION_JSON)
.content(json.getBytes()))
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON));
}
}
Unfortunately I receive the following error:
org.myproject.api.TestProjectsApi > testAddProject FAILED
java.lang.AssertionError: Status expected:<200> but was:<415>
at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:60)
at org.springframework.test.util.AssertionErrors.assertEquals(AssertionErrors.java:89)
at org.springframework.test.web.servlet.result.StatusResultMatchers$10.match(StatusResultMatchers.java:653)
at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:152)
at org.myproject.api.TestProjectsApi.testAddProject(TestProjectsApi.java:48)
I execute the tests in a terminal using the following Gradle command:
./gradlew --daemon test --info
UPD. I've added a print() to the request to see what is being sent/received:
org.myproject.api.TestProjectsApi > testAddProject STANDARD_OUT
MockHttpServletRequest:
HTTP Method = POST
Request URI = /projects/
Parameters = {}
Headers = {Content-Type=[application/json]}
Handler:
Type = org.myproject.api.ProjectsApi
Async:
Async started = false
Async result = null
Resolved Exception:
Type = org.springframework.web.HttpMediaTypeNotSupportedException
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
MockHttpServletResponse:
Status = 415
Error message = null
Headers = {Accept=[application/octet-stream, */*, text/plain;charset=ISO-8859-1, */*, application/xml, text/xml, application/*+xml, application/x-www-form-urlencoded, multipart/form-data]}
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
Gradle Test Executor 1 finished executing tests.
I ran into this issue and was able to fix it by adding the @EnableWebMvc annotation to my test's SpringContext class.
I had a similar case and I could solve it by adding both header-accept AND content-type.
Headers = {Accept=[application/json;charset=UTF-8],
Content-Type=[application/json;charset=UTF-8]}
In the test module:
MediaType MEDIA_TYPE_JSON_UTF8 = new MediaType("application", "json", java.nio.charset.Charset.forName("UTF-8"));
MockHttpServletRequestBuilder request = post("/myPostPath");
request.content(json);
request.locale(Locale.JAPANESE);
request.accept(MEDIA_TYPE_JSON_UTF8);
request.contentType(MEDIA_TYPE_JSON_UTF8);
mockMvc.perform(request)
.andDo(print())
.andExpect(status().isOk());
First I only put request.accept(..)
. But after adding request.contentType(..)
it finally worked.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With