Issue
I have made a program to consume a third part API: I have a service Called:NewsService
@Service
public class NewsService {
@Autowired
private NewsRepository newsRepository;
public List<News> getTopStories() throws Exception{
RestTemplate restTemplate = new RestTemplate();
JSONObject news = new JSONObject();
NewsStories newsentity = new NewsStories();
List<News> stories = new ArrayList<News>();
ObjectMapper mapper = new ObjectMapper();
String getUrl = "https://api.nytimes.com/svc/topstories/v2/home.json?api-key=84e19f8ee1c7489a97481d2ed85af15c";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<Map> entity = new HttpEntity<Map>(headers);
ResponseEntity<Map> newsList = restTemplate.exchange(getUrl, HttpMethod.GET, entity, Map.class);
if (newsList.getStatusCode() == HttpStatus.OK) {
news = new JSONObject(newsList.getBody());
newsentity = mapper.readValue(news.toString(),NewsStories.class);
newsentity.getStories().forEach(stories::add);
}
return stories;
}
}`
I have my controller
@RestController
@RequestMapping("/api/")
public class NewsController {
@Autowired
NewsService newsService = new NewsService();
@RequestMapping(value = "/news/topstories", method = RequestMethod.GET)
public @ResponseBody List<News> getNews() throws Exception {
return this.newsService.getTopStories();
}
}`
Everything is ok, however when i running my test (I cann't change it by internal audit control) Here my Test.
@SpringBootTest
@RunWith(SpringRunner.class)
public class ProjectApplicationTests {
private MockMvc mockMvc;
@Autowired
WebApplicationContext context;
@Before
public void setup() {
mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
}
@Test
public void Newstest_ok() throws Exception {
mockMvc.perform(get("/api/news/topstories" )).andDo(print())
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.title").exists())
.andExpect(MockMvcResultMatchers.jsonPath("$.section").exists());
}`
Next to run the program I have problem with the check validation Exist() in my program. Could you help me? below the log after to runt the test.
2018-07-18 09:40:49.100 INFO 23324 --- [ main] o.s.b.t.m.w.SpringBootMockServletContext : Initializing Spring FrameworkServlet '' 2018-07-18 09:40:49.100 INFO 23324 --- [
main] o.s.t.web.servlet.TestDispatcherServlet : FrameworkServlet '': initialization started 2018-07-18 09:40:49.116 INFO 23324 --- [
main] o.s.t.web.servlet.TestDispatcherServlet : FrameworkServlet '': initialization completed in 16 ms MockHttpServletRequest: HTTP Method = GET Request URI = /api/news/topstories Parameters = {} Headers = {} Body = Session Attrs = {} Handler: Type = com.example.project.Web.NewsController Method = public java.util.List com.example.project.Web.NewsController.getNews() throws java.lang.Exception 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=[application/json;charset=UTF-8]} Content type = application/json;charset=UTF-8 Body = [{"title":"Donald Trump, Barack Obama, European Union: Your Wednesday Briefing","section":"Briefing"},{"title":"New York Today: Will Green Roofs Get the Green Light?","section":"New York"},{"title":"California Today: Will a Representative’s Views on Russia Affect His Re-election Campaign?","section":"U.S."},{"title":"A Besieged Trump Says He Misspoke on Russian Election Meddling","section":"World"}] Forwarded URL = null Redirected URL = null Cookies = [] java.lang.AssertionError: No value at JSON path "$.title" at org.springframework.test.util.JsonPathExpectationsHelper.evaluateJsonPath(JsonPathExpectationsHelper.java:290) at org.springframework.test.util.JsonPathExpectationsHelper.assertExistsAndReturn(JsonPathExpectationsHelper.java:306) at org.springframework.test.util.JsonPathExpectationsHelper.exists(JsonPathExpectationsHelper.java:184) at org.springframework.test.web.servlet.result.JsonPathResultMatchers.lambda$exists$3(JsonPathResultMatchers.java:123) at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:178) at com.example.project.ProjectApplicationTests.Newstest_ok(ProjectApplicationTests.java:44) 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.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:73) at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:83) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) 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:251) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97) 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:190) 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) Caused by: com.jayway.jsonpath.PathNotFoundException: Expected to find an object with property ['title'] in path $ but found 'net.minidev.json.JSONArray'. This is not a json object according to the JsonProvider: 'com.jayway.jsonpath.spi.json.JsonSmartJsonProvider'. at com.jayway.jsonpath.internal.path.PropertyPathToken.evaluate(PropertyPathToken.java:71) at com.jayway.jsonpath.internal.path.RootPathToken.evaluate(RootPathToken.java:62) at com.jayway.jsonpath.internal.path.CompiledPath.evaluate(CompiledPath.java:53) at com.jayway.jsonpath.internal.path.CompiledPath.evaluate(CompiledPath.java:61) at com.jayway.jsonpath.JsonPath.read(JsonPath.java:187) at com.jayway.jsonpath.JsonPath.read(JsonPath.java:345) at com.jayway.jsonpath.JsonPath.read(JsonPath.java:329) at org.springframework.test.util.JsonPathExpectationsHelper.evaluateJsonPath(JsonPathExpectationsHelper.java:286) ... 36 more
`
With Postman http://localhost:8080/api/news/topstories I get Json data and status is 200 Ok.
Solution
As per JSON response we can see that controller is returning body as Array of Objects.
To access each object in Spring MVC Test use following assertion:
.andExpect(jsonPath("[0].title").value("titlevalue0"))
.andExpect(jsonPath("[1].title").value("titlevalue1"))
Answered By - Alien
Answer Checked By - Gilberto Lyons (JavaFixing Admin)