英文:
MockMVC with a @Query in my Repository or refactor my controller to not use it?
问题
我在我的存储库中有一个@Query,根据SQL查询将数据返回给我的控制器,我该如何模拟这个过程?
这是我的存储库:
package movieweb.movies.repository;
import movieweb.movies.models.UserMovies;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface UserMoviesRepository extends CrudRepository<UserMovies, Integer> {
@Query(value = "select * from movies, user_movies where movies.movie_id = user_movies.movie_id and uname = ?1", nativeQuery = true)
List<UserMovies> findByUname(String uname);
}
这是我的控制器:
package movieweb.movies.controllers;
import movieweb.movies.models.Movies;
import movieweb.movies.models.UserMovies;
import movieweb.movies.repository.UserMoviesRepository;
import org.apache.catalina.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.repository.Query;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
public class UserMoviesController {
@Autowired
private UserMoviesRepository umRepository;
@CrossOrigin
@PostMapping(path = "/newUserMovie")
public ResponseEntity<UserMovies> addNewUserMovie(@RequestBody UserMovies data){
umRepository.save(data);
return new ResponseEntity<UserMovies>(data, HttpStatus.CREATED);
}
@CrossOrigin
@GetMapping(path="/getUserMovies")
public List<UserMovies> getUsersMovies(){
return (List<UserMovies>) umRepository.findAll();
}
@CrossOrigin
@GetMapping(path = "/getUserMovies/{uname}")
public List<UserMovies> getUserMovies(@PathVariable String uname){
return umRepository.findByUname(uname);
}
@CrossOrigin
@DeleteMapping(path ="/deleteUserMovies/{id}")
ResponseEntity deleteUserMovie(@PathVariable Integer id) {
umRepository.deleteById(id);
return new ResponseEntity(HttpStatus.ACCEPTED);
}
@CrossOrigin
@PutMapping("/usermovie/update/{id}")
public ResponseEntity<UserMovies> updateMovie(@RequestBody UserMovies updateMovie, @PathVariable Integer id) {
return umRepository.findById(id)
.map(userMovies -> {
userMovies.setMovieId(updateMovie.getMovieId());
userMovies.setUname(updateMovie.getUname());
umRepository.save(userMovies);
return new ResponseEntity<UserMovies>(userMovies, HttpStatus.OK);
})
.orElseGet(() -> {
updateMovie.setMovieId(id);
umRepository.save(updateMovie);
return new ResponseEntity<UserMovies>(updateMovie, HttpStatus.OK);
});
}
}
这是我在测试中尝试做的:
@Test
void getUserMoviesPerUser() throws Exception {
ArrayList<UserMovies> userMovies = new ArrayList<>();
userMovies.add(new UserMovies(1, "jamie", 1));
userMovies.add(new UserMovies(2, "joe", 1));
userMovies.add(new UserMovies(3, "jamie", 2));
userMovies.add(new UserMovies(4, "joe", 2));
when(userMoviesRepository.findByUname("jamie")).thenReturn(userMovies);
mockMvc.perform(get("/getUserMovies/{uname}", "jamie"))
.andDo(print())
.andExpect(jsonPath("$", hasSize(2)))
.andExpect(jsonPath("$[0].userMovieID", is(1)))
.andExpect(jsonPath("$[0].uname", is("jamie")))
.andExpect(jsonPath("$[0].movieId", is(1)))
.andExpect(jsonPath("$[1].userMovieID", is(3)))
.andExpect(jsonPath("$[1].uname", is("jamie")))
.andExpect(jsonPath("$[1].movieId", is(1)));
Mockito.verify(userMoviesRepository, times(1)).findAll();
}
我面临的问题是,当我运行上面的测试时,我没有像我预期的那样得到只有2条记录,而是得到了4条。这在我无法依赖SQL来运行测试方面是有道理的。是否有更好的方法编写我的控制器,以根据movie_id获取数据?
英文:
I have a @Query in my Repository that I return data to my controller based on a SQL Query, how would I mock this?
Here is my Repository
package movieweb.movies.repository;
import movieweb.movies.models.UserMovies;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface UserMoviesRepository extends CrudRepository<UserMovies, Integer> {
@Query(value = "select * from movies, user_movies where movies.movie_id = user_movies.movie_id and uname = ?1", nativeQuery = true)
List<UserMovies> findByUname(String uname);
}
Here is my Controller
package movieweb.movies.controllers;
import movieweb.movies.models.Movies;
import movieweb.movies.models.UserMovies;
import movieweb.movies.repository.UserMoviesRepository;
import org.apache.catalina.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.repository.Query;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
public class UserMoviesController {
@Autowired
private UserMoviesRepository umRepository;
@CrossOrigin
@PostMapping(path = "/newUserMovie")
public ResponseEntity<UserMovies> addNewUserMovie(@RequestBody UserMovies data){
umRepository.save(data);
return new ResponseEntity<UserMovies>(data, HttpStatus.CREATED);
}
@CrossOrigin
@GetMapping(path="/getUserMovies")
public List<UserMovies> getUsersMovies(){
return (List<UserMovies>) umRepository.findAll();
}
@CrossOrigin
@GetMapping(path = "/getUserMovies/{uname}")
public List<UserMovies> getUserMovies(@PathVariable String uname){
return umRepository.findByUname(uname);
}
@CrossOrigin
@DeleteMapping(path ="/deleteUserMovies/{id}")
ResponseEntity deleteUserMovie(@PathVariable Integer id) {
umRepository.deleteById(id);
return new ResponseEntity(HttpStatus.ACCEPTED);
}
@CrossOrigin
@PutMapping("/usermovie/update/{id}")
public ResponseEntity<UserMovies> updateMovie(@RequestBody UserMovies updateMovie, @PathVariable Integer id) {
return umRepository.findById(id)
.map(userMovies -> {
userMovies.setMovieId(updateMovie.getMovieId());
userMovies.setUname(updateMovie.getUname());
umRepository.save(userMovies);
return new ResponseEntity<UserMovies>(userMovies, HttpStatus.OK);
})
.orElseGet(() -> {
updateMovie.setMovieId(id);
umRepository.save(updateMovie);
return new ResponseEntity<UserMovies>(updateMovie, HttpStatus.OK);
});
}
}
And here is what I am trying to do in my test
@Test
void getUserMoviesPerUser() throws Exception{
ArrayList<UserMovies> userMovies = new ArrayList<>();
userMovies.add(new UserMovies(1, "jamie", 1));
userMovies.add(new UserMovies(2, "joe", 1));
userMovies.add(new UserMovies(3, "jamie", 2));
userMovies.add(new UserMovies(4, "joe", 2));
when(userMoviesRepository.findByUname("jamie")).thenReturn(userMovies);
mockMvc.perform(get("/getUserMovies/{uname}", "jamie"))
.andDo(print())
.andExpect(jsonPath("$", hasSize(2)))
.andExpect(jsonPath("$[0].userMovieID", is(1)))
.andExpect(jsonPath("$[0].uname", is("jamie")))
.andExpect(jsonPath("$[0].movieId", is(1)))
.andExpect(jsonPath("$[1].userMovieID", is(3)))
.andExpect(jsonPath("$[1].uname", is("jamie")))
.andExpect(jsonPath("$[1].movieId", is(1)));
Mockito.verify(userMoviesRepository, times(1)).findAll();
}
The problem I am facing is when I run the test above I am not getting back just 2 records like I would expect, I get back 4. This makes sense in the fact that I cant depend on SQL to run tests. Is there a better way to write my controller to get the data based on movie_id?
答案1
得分: 2
@Test
void getUserMoviesPerUser() throws Exception {
ArrayList<UserMovies> userMovies = new ArrayList<>();
userMovies.add(new UserMovies(1, "jamie", 1));
userMovies.add(new UserMovies(2, "joe", 1));
when(userMoviesRepository.findByUname("jamie")).thenReturn(userMovies);
mockMvc.perform(get("/getUserMovies/{uname}", "jamie"))
.andDo(print())
.andExpect(jsonPath("$", hasSize(2)))
.andExpect(jsonPath("$[0].userMovieID", is(1)))
.andExpect(jsonPath("$[0].uname", is("jamie")))
.andExpect(jsonPath("$[0].movieId", is(1)))
.andExpect(jsonPath("$[1].userMovieID", is(3)))
.andExpect(jsonPath("$[1].uname", is("jamie")))
.andExpect(jsonPath("$[1].movieId", is(1)));
Mockito.verify(userMoviesRepository, times(1)).findAll();
}
英文:
In your code you are creating 4 records
for mocking then simply remove 2 of them
so that you have 2 records
as response.
@Test
void getUserMoviesPerUser() throws Exception{
ArrayList<UserMovies> userMovies = new ArrayList<>();
userMovies.add(new UserMovies(1, "jamie", 1));
userMovies.add(new UserMovies(2, "joe", 1));
when(userMoviesRepository.findByUname("jamie")).thenReturn(userMovies);
mockMvc.perform(get("/getUserMovies/{uname}", "jamie"))
.andDo(print())
.andExpect(jsonPath("$", hasSize(2)))
.andExpect(jsonPath("$[0].userMovieID", is(1)))
.andExpect(jsonPath("$[0].uname", is("jamie")))
.andExpect(jsonPath("$[0].movieId", is(1)))
.andExpect(jsonPath("$[1].userMovieID", is(3)))
.andExpect(jsonPath("$[1].uname", is("jamie")))
.andExpect(jsonPath("$[1].movieId", is(1)));
Mockito.verify(userMoviesRepository, times(1)).findAll();
}
答案2
得分: 0
@Test
void getUserMoviesPerUser() throws Exception{
ArrayList<UserMovies> userMovies = new ArrayList<>();
userMovies.add(new UserMovies(1, "jamie", 1));
userMovies.add(new UserMovies(3, "jamie", 2));
when(userMoviesRepository.findByUname("jamie")).thenReturn(userMovies);
mockMvc.perform(get("/getUserMovies/{uname}", "jamie"))
.andDo(print())
.andExpect(jsonPath("$", hasSize(2)))
.andExpect(jsonPath("$[0].userMovieID", is(1)))
.andExpect(jsonPath("$[0].uname", is("jamie")))
.andExpect(jsonPath("$[0].movieId", is(1)))
.andExpect(jsonPath("$[1].userMovieID", is(3)))
.andExpect(jsonPath("$[1].uname", is("jamie")))
.andExpect(jsonPath("$[1].movieId", is(1)));
Mockito.verify(userMoviesRepository, times(1)).findAll();
}
英文:
I think you need to return the only records you were expecting. like
@Test
void getUserMoviesPerUser() throws Exception{
ArrayList<UserMovies> userMovies = new ArrayList<>();
userMovies.add(new UserMovies(1, "jamie", 1));
userMovies.add(new UserMovies(3, "jamie", 2));
when(userMoviesRepository.findByUname("jamie")).thenReturn(userMovies);
mockMvc.perform(get("/getUserMovies/{uname}", "jamie"))
.andDo(print())
.andExpect(jsonPath("$", hasSize(2)))
.andExpect(jsonPath("$[0].userMovieID", is(1)))
.andExpect(jsonPath("$[0].uname", is("jamie")))
.andExpect(jsonPath("$[0].movieId", is(1)))
.andExpect(jsonPath("$[1].userMovieID", is(3)))
.andExpect(jsonPath("$[1].uname", is("jamie")))
.andExpect(jsonPath("$[1].movieId", is(1)));
Mockito.verify(userMoviesRepository, times(1)).findAll();
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论