问题
I have problems with mockMVC and test written with that. My tests fails. I have two tests methods:
@Test
public void getPersonsForApiConsumerTest() throws Exception {
mockMvc.perform(get(getUri("/consumers/1/persons")))
.andExpect(status().isOk())
.andExpect(jsonPath("$", hasSize(2)))
.andExpect(jsonPath("$[1].name", is("Ligza")))
.andExpect(jsonPath("$[2].name", is("Vekrir")));
}
@Test
public void getPersonsForApiConsumerMapTest() throws Exception {
mockMvc.perform(get(getUri("/consumers/1/persons/map")))
.andExpect(status().isOk())
.andExpect(jsonPath("$[1].name", is("Verkir")))
.andExpect(jsonPath("$[2].name", is("Ligza")));
}
Rest methods with mapping:
@RequestMapping(value = "/{consumerId}/persons")
public List<PersonDto> getPersonsForApiConsumer(@PathVariable("consumerId") Integer consumerId) throws IOException {
return apiConsumerService.getPersonsListForApiConsumer(consumerId);
}
@RequestMapping(value = "/{consumerId}/persons/map")
public Map<ApiConsumerPersonRole, List<Person>> getPersonsForApiConsumerMap(@PathVariable("consumerId") Integer consumerId) throws IOException {
return apiConsumerService.getPersonsMapForApiConsumer(consumerId);
}
By Postman I can gain data such:
for list:
[
{
"id": 1,
"firstName": "Ligza",
"lastName": "Zetasor",
"role": "REPRESENTATIVE",
"phone": "123123123",
"email": "ligza.zetasor@gmail.com"
},
{
"id": 4,
"firstName": "Vekrir",
"lastName": "Omegaram",
"role": "SECURITY_OFFICER",
"phone": "354654545",
"email": "vekrir.omegaram@gmail.com"
}
]
for map:
{
"SECURITY_OFFICER": [
{
"id": 4,
"firstName": "Vekrir",
"lastName": "Omegaram",
"telephone": "354654545",
"email": "vekrir.omegaram@gmail.com"
}
],
"REPRESENTATIVE": [
{
"id": 1,
"firstName": "Ligza",
"lastName": "Zetasor",
"telephone": "123123123",
"email": "ligza.zetasor@gmail.com"
}
],
"COMPLAINT_OFFICER": [],
"LOCAL_REPRESENTATIVE": []
}
I dont have any clue how to write it properly. I want to check the data inside this list and map.
Is it possible to stream it into that collection or check it easily in the way it is wriiten already?
Edit: logs:
java.lang.AssertionError: No value at JSON path "$[1].firstname", exception: No results for path: $[1]['firstname']
at org.springframework.test.util.JsonPathExpectationsHelper.evaluateJsonPath(JsonPathExpectationsHelper.java:245)
at org.springframework.test.util.JsonPathExpectationsHelper.assertValue(JsonPathExpectationsHelper.java:73)
at org.springframework.test.web.servlet.result.JsonPathResultMatchers$1.match(JsonPathResultMatchers.java:87)
at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:171)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Process finished with exit code -1
MockHttpServletResponse:
Status = 200
Error message = null
Headers = {X-Content-Type-Options=[nosniff], X-XSS-Protection=[1; mode=block], Cache-Control=[no-cache, no-store, max-age=0, must-revalidate], Pragma=[no-cache], Expires=[0], X-Frame-Options=[DENY], Content-Type=[application/json;charset=UTF-8]}
Content type = application/json;charset=UTF-8
Body = {"COMPLAINT_OFFICER":[],"REPRESENTATIVE":[{"id":1,"firstName":"Ligza","lastName":"Zetasor","telephone":"123123123","email":"ligza.zetasor@gmail.com"}],"LOCAL_REPRESENTATIVE":[],"SECURITY_OFFICER":[{"id":4,"firstName":"Vekrir","lastName":"Omegaram","telephone":"354654545","email":"vekrir.omegaram@gmail.com"}]}
Forwarded URL = null
Redirected URL = null
Cookies = []
java.lang.AssertionError: No value at JSON path "$[1].firstname", exception: Filter: [1]['firstname'] can only be applied to arrays. Current context is: {COMPLAINT_OFFICER=[], REPRESENTATIVE=[{"id":1,"firstName":"Ligza","lastName":"Zetasor","telephone":"123123123","email":"ligza.zetasor@gmail.com"}], LOCAL_REPRESENTATIVE=[], SECURITY_OFFICER=[{"id":4,"firstName":"Vekrir","lastName":"Omegaram","telephone":"354654545","email":"vekrir.omegaram@gmail.com"}]}
at org.springframework.test.util.JsonPathExpectationsHelper.evaluateJsonPath(JsonPathExpectationsHelper.java:245)
at org.springframework.test.util.JsonPathExpectationsHelper.assertValue(JsonPathExpectationsHelper.java:73)
at org.springframework.test.web.servlet.result.JsonPathResultMatchers$1.match(JsonPathResultMatchers.java:87)
at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:171)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
回答1:
The jsonPath
helpers are very useful for asserting your responses are valid from the perspective of the consumers of your API; these consumers receive a JSON repsonse so it makes sense to perform your assertions on that JSON.
The following assertions will work for the payload from /consumers/1/persons
.andExpect(jsonPath("$[0].firstName", is("Ligza")))
.andExpect(jsonPath("$[1].firstName", is("Vekrir")))
So, the array is 0-based and you access entries in each element by the (case sensitive) name.
However, if you really want to assert against the original types (e.g. PersonDto
) then you can read the entire JSON string and use a JSON mapper (such as Jackson or Gson) to deserialize it back into its original class representation. For example:
MvcResult result = mockMvc.perform(get(getUri("/consumers/1/persons")))
.andExpect(status().isOk())
.andReturn();
ObjectMapper mapper = new ObjectMapper();
// this uses a TypeReference to inform Jackson about the Lists's generic type
List<PersonDto> actual = mapper.readValue(result.getResponse().getContentAsString(), new TypeReference<List<PersonDto>>() {});
// now just assert equality (or whatever) against the actual PersonDto
来源:https://stackoverflow.com/questions/46885972/mockmvc-in-junit-tests-checking-result-for-listobject-and-mapenum-object