英文:
MockMvc and Mockito - java.lang.AssertionError: JSON path "$" Expected: a collection with size <2> but: collection size was <0>
问题
我不明白为什么在这里会出现这个错误。有什么想法吗?
这是我的仓库代码
package movieweb.movies.repository;
import movieweb.movies.models.Movies;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface MoviesRepository extends CrudRepository<Movies, Integer> {
}
这是我的控制器代码。
package movieweb.movies.controllers;
import movieweb.movies.models.Movies;
import movieweb.movies.models.UserMovies;
import movieweb.movies.repository.MoviesRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.server.ResponseStatusException;
@RestController
public class MoviesController {
@Autowired
private MoviesRepository moviesRepository;
@Autowired
private RestTemplate restTemplate;
@CrossOrigin
@GetMapping(path = "/movies")
public List<Movies> movies(){
List<Movies> allMovies = (List<Movies>) moviesRepository.findAll();
if (!allMovies.isEmpty()){
return allMovies;
} else {
throw new ResponseStatusException(
HttpStatus.NOT_FOUND, "Movies not found"
);
}
}
// @CrossOrigin
// @RequestMapping(path = "movies/user/{id}")
// public List<Movies> movie(@PathVariable("id") int id){
// return this.movies().stream().map(movie -> {
// Users[] user = restTemplate.getForObject("http://127.0.0.1:8082/users/" + id, Users[].class);
// return new Movies(movie.getMovieId(), movie.getMovieName(), "Description");
// })
// .collect(Collectors.toList());
// }
@CrossOrigin
@GetMapping(path="/movie/{id}")
public Movies getMovie(@PathVariable Integer id){
return moviesRepository.findById(id)
.orElseThrow(() -> new ResponseStatusException(
HttpStatus.NOT_FOUND, "Movie not found"
) );
}
@CrossOrigin
@DeleteMapping("/movie/delete/{id}")
void deleteMovie(@PathVariable Integer id) {
moviesRepository.deleteById(id);
}
@CrossOrigin
@PutMapping("/movie/update/{id}")
Movies updateMovie(@RequestBody Movies updateMovie, @PathVariable Integer id) {
return moviesRepository.findById(id)
.map(Movies -> {
Movies.setMovieName(updateMovie.getMovieName());
Movies.setMovieDescription(updateMovie.getMovieDescription());
return moviesRepository.save(Movies);
})
.orElseGet(() -> {
updateMovie.setMovieId(id);
return moviesRepository.save(updateMovie);
});
}
@CrossOrigin
@PostMapping(path="/newMovie")
public Movies addNewMovie (@RequestBody Movies data) {
return moviesRepository.save(data);
}
}
这是我的测试(**已更新**)
package movieweb.movies;
import movieweb.movies.controllers.MoviesController;
import movieweb.movies.models.Movies;
import movieweb.movies.repository.MoviesRepository;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import org.testng.annotations.BeforeMethod;
import java.util.ArrayList;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest
@AutoConfigureMockMvc
class MovieApplicationTests {
@Autowired
MockMvc mockMvc;
@MockBean
MoviesRepository moviesRepository;
@MockBean
MoviesController moviesController;
@Autowired
private WebApplicationContext webApplicationContext;
@BeforeMethod
public void init() {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
@Test
void getAllMovies() throws Exception{
ArrayList<Movies> moviesList = new ArrayList<Movies>();
moviesList.add(new Movies(1, "Star Wars", "A New Hope"));
moviesList.add(new Movies(2, "Star Wars", "Empire Strikes Back"));
when(moviesRepository.findAll()).thenReturn(moviesList);
mockMvc.perform(get("/movies"))
.andExpect(status().isOk())
.andExpect(jsonPath("$", hasSize(2)))
.andExpect(jsonPath("$[0].movieName", is("Star Wars")))
.andExpect(jsonPath("$[0].movieDescription", is("A New Hope")))
.andExpect(jsonPath("$[1].movieName", is("Star Wars")))
.andExpect(jsonPath("$[1].movieDescription", is("Empire Strikes Back")));
Mockito.verify(moviesRepository, times(1)).findAll();
}
}
错误信息在堆栈跟踪中如下....
java.lang.AssertionError: JSON path "$"
Expected: a collection with size <2>
but: collection size was <0>
为什么是零而不是我在电影列表ArrayList中创建的2个项目?
我猜这与我的配置有关?
英文:
I have no idea why I am getting this error here. Any thoughts?
Here is my repository code
package movieweb.movies.repository;
import movieweb.movies.models.Movies;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface MoviesRepository extends CrudRepository<Movies, Integer> {
}
Here is my Controller code.
package movieweb.movies.controllers;
import movieweb.movies.models.Movies;
import movieweb.movies.models.UserMovies;
import movieweb.movies.repository.MoviesRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.server.ResponseStatusException;
@RestController
public class MoviesController {
@Autowired
private MoviesRepository moviesRepository;
@Autowired
private RestTemplate restTemplate;
@CrossOrigin
@GetMapping(path = "/movies")
public List<Movies> movies(){
List<Movies> allMovies = (List<Movies>) moviesRepository.findAll();
if (!allMovies.isEmpty()){
return allMovies;
} else {
throw new ResponseStatusException(
HttpStatus.NOT_FOUND, "Movies not found"
);
}
}
// @CrossOrigin
// @RequestMapping(path = "movies/user/{id}")
// public List<Movies> movie(@PathVariable("id") int id){
// return this.movies().stream().map(movie -> {
// Users[] user = restTemplate.getForObject("http://127.0.0.1:8082/users/" + id, Users[].class);
// return new Movies(movie.getMovieId(), movie.getMovieName(), "Description");
// })
// .collect(Collectors.toList());
// }
@CrossOrigin
@GetMapping(path="/movie/{id}")
public Movies getMovie(@PathVariable Integer id){
return moviesRepository.findById(id)
.orElseThrow(() -> new ResponseStatusException(
HttpStatus.NOT_FOUND, "Movie not found"
) );
}
@CrossOrigin
@DeleteMapping("/movie/delete/{id}")
void deleteMovie(@PathVariable Integer id) {
moviesRepository.deleteById(id);
}
@CrossOrigin
@PutMapping("/movie/update/{id}")
Movies updateMovie(@RequestBody Movies updateMovie, @PathVariable Integer id) {
return moviesRepository.findById(id)
.map(Movies -> {
Movies.setMovieName(updateMovie.getMovieName());
Movies.setMovieDescription(updateMovie.getMovieDescription());
return moviesRepository.save(Movies);
})
.orElseGet(() -> {
updateMovie.setMovieId(id);
return moviesRepository.save(updateMovie);
});
}
@CrossOrigin
@PostMapping(path="/newMovie")
public Movies addNewMovie (@RequestBody Movies data) {
return moviesRepository.save(data);
}
}
and here is my test (updated)
package movieweb.movies;
import movieweb.movies.controllers.MoviesController;
import movieweb.movies.models.Movies;
import movieweb.movies.repository.MoviesRepository;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import org.testng.annotations.BeforeMethod;
import java.util.ArrayList;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest
@AutoConfigureMockMvc
class MovieApplicationTests {
@Autowired
MockMvc mockMvc;
@MockBean
MoviesRepository moviesRepository;
@MockBean
MoviesController moviesController;
@Autowired
private WebApplicationContext webApplicationContext;
@BeforeMethod
public void init() {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
@Test
void getAllMovies() throws Exception{
ArrayList<Movies> moviesList = new ArrayList<Movies>();
moviesList.add(new Movies(1, "Star Wars", "A New Hope"));
moviesList.add(new Movies(2, "Star Wars", "Empire Strikes Back"));
when(moviesRepository.findAll()).thenReturn(moviesList);
mockMvc.perform(get("/movies"))
.andExpect(status().isOk())
.andExpect(jsonPath("$", hasSize(2)))
.andExpect(jsonPath("$[0].movieName", is("Star Wars")))
.andExpect(jsonPath("$[0].movieDescription", is("A New Hope")))
.andExpect(jsonPath("$[1].movieName", is("Star Wars")))
.andExpect(jsonPath("$[1].movieDescription", is("Empire Strikes Back")));
Mockito.verify(moviesRepository, times(1)).findAll();
}
}
The error I am getting in my stacktrace is the following....
java.lang.AssertionError: JSON path "$"
Expected: a collection with size <2>
but: collection size was <0>
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
你正在对你的控制器进行模拟:
@MockBean
MoviesController moviesController;
因此,你用这个模拟替换了要测试的真实控制器。
如果想使用真实的控制器,你需要去掉这些代码。
为了进一步提升,可以了解一下 @WebMvcTest
,它可以只测试你应用程序的 web 部分。
英文:
You are mocking your controller:
@MockBean
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论