MockMvc and Mockito – java.lang.AssertionError: JSON path "$" Expected: a collection with size <2> but: collection size was <0>

huangapple 未分类评论70阅读模式
英文:

MockMvc and Mockito - java.lang.AssertionError: JSON path "$" Expected: a collection with size <2> but: collection size was <0>

问题

  1. 我不明白为什么在这里会出现这个错误。有什么想法吗?
  2. 这是我的仓库代码
  3. package movieweb.movies.repository;
  4. import movieweb.movies.models.Movies;
  5. import org.springframework.data.repository.CrudRepository;
  6. import org.springframework.stereotype.Repository;
  7. @Repository
  8. public interface MoviesRepository extends CrudRepository<Movies, Integer> {
  9. }
  10. 这是我的控制器代码。
  11. package movieweb.movies.controllers;
  12. import movieweb.movies.models.Movies;
  13. import movieweb.movies.models.UserMovies;
  14. import movieweb.movies.repository.MoviesRepository;
  15. import org.springframework.beans.factory.annotation.Autowired;
  16. import org.springframework.http.HttpStatus;
  17. import org.springframework.web.bind.annotation.*;
  18. import java.util.List;
  19. import org.springframework.web.client.RestTemplate;
  20. import org.springframework.web.server.ResponseStatusException;
  21. @RestController
  22. public class MoviesController {
  23. @Autowired
  24. private MoviesRepository moviesRepository;
  25. @Autowired
  26. private RestTemplate restTemplate;
  27. @CrossOrigin
  28. @GetMapping(path = "/movies")
  29. public List<Movies> movies(){
  30. List<Movies> allMovies = (List<Movies>) moviesRepository.findAll();
  31. if (!allMovies.isEmpty()){
  32. return allMovies;
  33. } else {
  34. throw new ResponseStatusException(
  35. HttpStatus.NOT_FOUND, "Movies not found"
  36. );
  37. }
  38. }
  39. // @CrossOrigin
  40. // @RequestMapping(path = "movies/user/{id}")
  41. // public List<Movies> movie(@PathVariable("id") int id){
  42. // return this.movies().stream().map(movie -> {
  43. // Users[] user = restTemplate.getForObject("http://127.0.0.1:8082/users/" + id, Users[].class);
  44. // return new Movies(movie.getMovieId(), movie.getMovieName(), "Description");
  45. // })
  46. // .collect(Collectors.toList());
  47. // }
  48. @CrossOrigin
  49. @GetMapping(path="/movie/{id}")
  50. public Movies getMovie(@PathVariable Integer id){
  51. return moviesRepository.findById(id)
  52. .orElseThrow(() -> new ResponseStatusException(
  53. HttpStatus.NOT_FOUND, "Movie not found"
  54. ) );
  55. }
  56. @CrossOrigin
  57. @DeleteMapping("/movie/delete/{id}")
  58. void deleteMovie(@PathVariable Integer id) {
  59. moviesRepository.deleteById(id);
  60. }
  61. @CrossOrigin
  62. @PutMapping("/movie/update/{id}")
  63. Movies updateMovie(@RequestBody Movies updateMovie, @PathVariable Integer id) {
  64. return moviesRepository.findById(id)
  65. .map(Movies -> {
  66. Movies.setMovieName(updateMovie.getMovieName());
  67. Movies.setMovieDescription(updateMovie.getMovieDescription());
  68. return moviesRepository.save(Movies);
  69. })
  70. .orElseGet(() -> {
  71. updateMovie.setMovieId(id);
  72. return moviesRepository.save(updateMovie);
  73. });
  74. }
  75. @CrossOrigin
  76. @PostMapping(path="/newMovie")
  77. public Movies addNewMovie (@RequestBody Movies data) {
  78. return moviesRepository.save(data);
  79. }
  80. }
  81. 这是我的测试(**已更新**)
  82. package movieweb.movies;
  83. import movieweb.movies.controllers.MoviesController;
  84. import movieweb.movies.models.Movies;
  85. import movieweb.movies.repository.MoviesRepository;
  86. import org.junit.jupiter.api.Test;
  87. import org.mockito.Mock;
  88. import org.mockito.Mockito;
  89. import org.springframework.beans.factory.annotation.Autowired;
  90. import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
  91. import org.springframework.boot.test.context.SpringBootTest;
  92. import org.springframework.boot.test.mock.mockito.MockBean;
  93. import org.springframework.test.web.servlet.MockMvc;
  94. import org.springframework.test.web.servlet.setup.MockMvcBuilders;
  95. import org.springframework.web.context.WebApplicationContext;
  96. import org.testng.annotations.BeforeMethod;
  97. import java.util.ArrayList;
  98. import static org.hamcrest.Matchers.is;
  99. import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
  100. import static org.mockito.Mockito.times;
  101. import static org.mockito.Mockito.when;
  102. import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
  103. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
  104. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
  105. @SpringBootTest
  106. @AutoConfigureMockMvc
  107. class MovieApplicationTests {
  108. @Autowired
  109. MockMvc mockMvc;
  110. @MockBean
  111. MoviesRepository moviesRepository;
  112. @MockBean
  113. MoviesController moviesController;
  114. @Autowired
  115. private WebApplicationContext webApplicationContext;
  116. @BeforeMethod
  117. public void init() {
  118. mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
  119. }
  120. @Test
  121. void getAllMovies() throws Exception{
  122. ArrayList<Movies> moviesList = new ArrayList<Movies>();
  123. moviesList.add(new Movies(1, "Star Wars", "A New Hope"));
  124. moviesList.add(new Movies(2, "Star Wars", "Empire Strikes Back"));
  125. when(moviesRepository.findAll()).thenReturn(moviesList);
  126. mockMvc.perform(get("/movies"))
  127. .andExpect(status().isOk())
  128. .andExpect(jsonPath("$", hasSize(2)))
  129. .andExpect(jsonPath("$[0].movieName", is("Star Wars")))
  130. .andExpect(jsonPath("$[0].movieDescription", is("A New Hope")))
  131. .andExpect(jsonPath("$[1].movieName", is("Star Wars")))
  132. .andExpect(jsonPath("$[1].movieDescription", is("Empire Strikes Back")));
  133. Mockito.verify(moviesRepository, times(1)).findAll();
  134. }
  135. }
  136. 错误信息在堆栈跟踪中如下....
  137. java.lang.AssertionError: JSON path "$"
  138. Expected: a collection with size <2>
  139. but: collection size was <0>
  140. 为什么是零而不是我在电影列表ArrayList中创建的2个项目?
  141. 我猜这与我的配置有关?
英文:

I have no idea why I am getting this error here. Any thoughts?

Here is my repository code

  1. package movieweb.movies.repository;
  2. import movieweb.movies.models.Movies;
  3. import org.springframework.data.repository.CrudRepository;
  4. import org.springframework.stereotype.Repository;
  5. @Repository
  6. public interface MoviesRepository extends CrudRepository&lt;Movies, Integer&gt; {
  7. }

Here is my Controller code.

  1. package movieweb.movies.controllers;
  2. import movieweb.movies.models.Movies;
  3. import movieweb.movies.models.UserMovies;
  4. import movieweb.movies.repository.MoviesRepository;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.http.HttpStatus;
  7. import org.springframework.web.bind.annotation.*;
  8. import java.util.List;
  9. import org.springframework.web.client.RestTemplate;
  10. import org.springframework.web.server.ResponseStatusException;
  11. @RestController
  12. public class MoviesController {
  13. @Autowired
  14. private MoviesRepository moviesRepository;
  15. @Autowired
  16. private RestTemplate restTemplate;
  17. @CrossOrigin
  18. @GetMapping(path = &quot;/movies&quot;)
  19. public List&lt;Movies&gt; movies(){
  20. List&lt;Movies&gt; allMovies = (List&lt;Movies&gt;) moviesRepository.findAll();
  21. if (!allMovies.isEmpty()){
  22. return allMovies;
  23. } else {
  24. throw new ResponseStatusException(
  25. HttpStatus.NOT_FOUND, &quot;Movies not found&quot;
  26. );
  27. }
  28. }
  29. // @CrossOrigin
  30. // @RequestMapping(path = &quot;movies/user/{id}&quot;)
  31. // public List&lt;Movies&gt; movie(@PathVariable(&quot;id&quot;) int id){
  32. // return this.movies().stream().map(movie -&gt; {
  33. // Users[] user = restTemplate.getForObject(&quot;http://127.0.0.1:8082/users/&quot; + id, Users[].class);
  34. // return new Movies(movie.getMovieId(), movie.getMovieName(), &quot;Description&quot;);
  35. // })
  36. // .collect(Collectors.toList());
  37. // }
  38. @CrossOrigin
  39. @GetMapping(path=&quot;/movie/{id}&quot;)
  40. public Movies getMovie(@PathVariable Integer id){
  41. return moviesRepository.findById(id)
  42. .orElseThrow(() -&gt; new ResponseStatusException(
  43. HttpStatus.NOT_FOUND, &quot;Movie not found&quot;
  44. ) );
  45. }
  46. @CrossOrigin
  47. @DeleteMapping(&quot;/movie/delete/{id}&quot;)
  48. void deleteMovie(@PathVariable Integer id) {
  49. moviesRepository.deleteById(id);
  50. }
  51. @CrossOrigin
  52. @PutMapping(&quot;/movie/update/{id}&quot;)
  53. Movies updateMovie(@RequestBody Movies updateMovie, @PathVariable Integer id) {
  54. return moviesRepository.findById(id)
  55. .map(Movies -&gt; {
  56. Movies.setMovieName(updateMovie.getMovieName());
  57. Movies.setMovieDescription(updateMovie.getMovieDescription());
  58. return moviesRepository.save(Movies);
  59. })
  60. .orElseGet(() -&gt; {
  61. updateMovie.setMovieId(id);
  62. return moviesRepository.save(updateMovie);
  63. });
  64. }
  65. @CrossOrigin
  66. @PostMapping(path=&quot;/newMovie&quot;)
  67. public Movies addNewMovie (@RequestBody Movies data) {
  68. return moviesRepository.save(data);
  69. }
  70. }

and here is my test (updated)

  1. package movieweb.movies;
  2. import movieweb.movies.controllers.MoviesController;
  3. import movieweb.movies.models.Movies;
  4. import movieweb.movies.repository.MoviesRepository;
  5. import org.junit.jupiter.api.Test;
  6. import org.mockito.Mock;
  7. import org.mockito.Mockito;
  8. import org.springframework.beans.factory.annotation.Autowired;
  9. import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
  10. import org.springframework.boot.test.context.SpringBootTest;
  11. import org.springframework.boot.test.mock.mockito.MockBean;
  12. import org.springframework.test.web.servlet.MockMvc;
  13. import org.springframework.test.web.servlet.setup.MockMvcBuilders;
  14. import org.springframework.web.context.WebApplicationContext;
  15. import org.testng.annotations.BeforeMethod;
  16. import java.util.ArrayList;
  17. import static org.hamcrest.Matchers.is;
  18. import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
  19. import static org.mockito.Mockito.times;
  20. import static org.mockito.Mockito.when;
  21. import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
  22. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
  23. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
  24. @SpringBootTest
  25. @AutoConfigureMockMvc
  26. class MovieApplicationTests {
  27. @Autowired
  28. MockMvc mockMvc;
  29. @MockBean
  30. MoviesRepository moviesRepository;
  31. @MockBean
  32. MoviesController moviesController;
  33. @Autowired
  34. private WebApplicationContext webApplicationContext;
  35. @BeforeMethod
  36. public void init() {
  37. mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
  38. }
  39. @Test
  40. void getAllMovies() throws Exception{
  41. ArrayList&lt;Movies&gt; moviesList = new ArrayList&lt;Movies&gt;();
  42. moviesList.add(new Movies(1, &quot;Star Wars&quot;, &quot;A New Hope&quot;));
  43. moviesList.add(new Movies(2, &quot;Star Wars&quot;, &quot;Empire Strikes Back&quot;));
  44. when(moviesRepository.findAll()).thenReturn(moviesList);
  45. mockMvc.perform(get(&quot;/movies&quot;))
  46. .andExpect(status().isOk())
  47. .andExpect(jsonPath(&quot;$&quot;, hasSize(2)))
  48. .andExpect(jsonPath(&quot;$[0].movieName&quot;, is(&quot;Star Wars&quot;)))
  49. .andExpect(jsonPath(&quot;$[0].movieDescription&quot;, is(&quot;A New Hope&quot;)))
  50. .andExpect(jsonPath(&quot;$[1].movieName&quot;, is(&quot;Star Wars&quot;)))
  51. .andExpect(jsonPath(&quot;$[1].movieDescription&quot;, is(&quot;Empire Strikes Back&quot;)));
  52. Mockito.verify(moviesRepository, times(1)).findAll();
  53. }
  54. }

The error I am getting in my stacktrace is the following....

  1. java.lang.AssertionError: JSON path &quot;$&quot;
  2. Expected: a collection with size &lt;2&gt;
  3. but: collection size was &lt;0&gt;

Why is it zero and not the 2 items I created in my movieList ArrayList?

I'm guessing its something to do with my configuration?

答案1

得分: 1

你正在对你的控制器进行模拟:

  1. @MockBean
  2. MoviesController moviesController;

因此,你用这个模拟替换了要测试的真实控制器。
如果想使用真实的控制器,你需要去掉这些代码。

为了进一步提升,可以了解一下 @WebMvcTest,它可以只测试你应用程序的 web 部分。

英文:

You are mocking your controller:

  1. @MockBean
  2. MoviesController moviesController;

Thus, you replaced the real controller under test with this mock.
To have real controller you need to get rid of these lines.

To further improve, learn about @WebMvcTest to test only the web slice of your app.

huangapple
  • 本文由 发表于 2020年3月15日 10:35:27
  • 转载请务必保留本文链接:https://java.coder-hub.com/60689219.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定