MockMVC with a @Query in my Repository or refactor my controller to not use it?

huangapple go评论93阅读模式
英文:

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&lt;UserMovies, Integer&gt; {
@Query(value = &quot;select * from movies, user_movies where movies.movie_id = user_movies.movie_id and uname = ?1&quot;, nativeQuery = true)
List&lt;UserMovies&gt; 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 = &quot;/newUserMovie&quot;)
public ResponseEntity&lt;UserMovies&gt; addNewUserMovie(@RequestBody UserMovies data){
umRepository.save(data);
return new ResponseEntity&lt;UserMovies&gt;(data, HttpStatus.CREATED);
}
@CrossOrigin
@GetMapping(path=&quot;/getUserMovies&quot;)
public  List&lt;UserMovies&gt; getUsersMovies(){
return (List&lt;UserMovies&gt;) umRepository.findAll();
}
@CrossOrigin
@GetMapping(path = &quot;/getUserMovies/{uname}&quot;)
public  List&lt;UserMovies&gt; getUserMovies(@PathVariable String uname){
return umRepository.findByUname(uname);
}
@CrossOrigin
@DeleteMapping(path =&quot;/deleteUserMovies/{id}&quot;)
ResponseEntity deleteUserMovie(@PathVariable Integer id) {
umRepository.deleteById(id);
return new ResponseEntity(HttpStatus.ACCEPTED);
}
@CrossOrigin
@PutMapping(&quot;/usermovie/update/{id}&quot;)
public ResponseEntity&lt;UserMovies&gt; updateMovie(@RequestBody UserMovies updateMovie, @PathVariable Integer id) {
return umRepository.findById(id)
.map(userMovies -&gt; {
userMovies.setMovieId(updateMovie.getMovieId());
userMovies.setUname(updateMovie.getUname());
umRepository.save(userMovies);
return new ResponseEntity&lt;UserMovies&gt;(userMovies, HttpStatus.OK);
})
.orElseGet(() -&gt; {
updateMovie.setMovieId(id);
umRepository.save(updateMovie);
return new ResponseEntity&lt;UserMovies&gt;(updateMovie, HttpStatus.OK);
});
}
}

And here is what I am trying to do in my test

@Test
void getUserMoviesPerUser() throws Exception{
ArrayList&lt;UserMovies&gt; userMovies = new ArrayList&lt;&gt;();
userMovies.add(new UserMovies(1, &quot;jamie&quot;, 1));
userMovies.add(new UserMovies(2, &quot;joe&quot;, 1));
userMovies.add(new UserMovies(3, &quot;jamie&quot;, 2));
userMovies.add(new UserMovies(4, &quot;joe&quot;, 2));
when(userMoviesRepository.findByUname(&quot;jamie&quot;)).thenReturn(userMovies);
mockMvc.perform(get(&quot;/getUserMovies/{uname}&quot;, &quot;jamie&quot;))
.andDo(print())
.andExpect(jsonPath(&quot;$&quot;, hasSize(2)))
.andExpect(jsonPath(&quot;$[0].userMovieID&quot;, is(1)))
.andExpect(jsonPath(&quot;$[0].uname&quot;, is(&quot;jamie&quot;)))
.andExpect(jsonPath(&quot;$[0].movieId&quot;, is(1)))
.andExpect(jsonPath(&quot;$[1].userMovieID&quot;, is(3)))
.andExpect(jsonPath(&quot;$[1].uname&quot;, is(&quot;jamie&quot;)))
.andExpect(jsonPath(&quot;$[1].movieId&quot;, 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&lt;UserMovies&gt; userMovies = new ArrayList&lt;&gt;();
userMovies.add(new UserMovies(1, &quot;jamie&quot;, 1));
userMovies.add(new UserMovies(2, &quot;joe&quot;, 1));
when(userMoviesRepository.findByUname(&quot;jamie&quot;)).thenReturn(userMovies);
mockMvc.perform(get(&quot;/getUserMovies/{uname}&quot;, &quot;jamie&quot;))
.andDo(print())
.andExpect(jsonPath(&quot;$&quot;, hasSize(2)))
.andExpect(jsonPath(&quot;$[0].userMovieID&quot;, is(1)))
.andExpect(jsonPath(&quot;$[0].uname&quot;, is(&quot;jamie&quot;)))
.andExpect(jsonPath(&quot;$[0].movieId&quot;, is(1)))
.andExpect(jsonPath(&quot;$[1].userMovieID&quot;, is(3)))
.andExpect(jsonPath(&quot;$[1].uname&quot;, is(&quot;jamie&quot;)))
.andExpect(jsonPath(&quot;$[1].movieId&quot;, 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&lt;UserMovies&gt; userMovies = new ArrayList&lt;&gt;();
userMovies.add(new UserMovies(1, &quot;jamie&quot;, 1));
userMovies.add(new UserMovies(3, &quot;jamie&quot;, 2));
when(userMoviesRepository.findByUname(&quot;jamie&quot;)).thenReturn(userMovies);
mockMvc.perform(get(&quot;/getUserMovies/{uname}&quot;, &quot;jamie&quot;))
.andDo(print())
.andExpect(jsonPath(&quot;$&quot;, hasSize(2)))
.andExpect(jsonPath(&quot;$[0].userMovieID&quot;, is(1)))
.andExpect(jsonPath(&quot;$[0].uname&quot;, is(&quot;jamie&quot;)))
.andExpect(jsonPath(&quot;$[0].movieId&quot;, is(1)))
.andExpect(jsonPath(&quot;$[1].userMovieID&quot;, is(3)))
.andExpect(jsonPath(&quot;$[1].uname&quot;, is(&quot;jamie&quot;)))
.andExpect(jsonPath(&quot;$[1].movieId&quot;, is(1)));
Mockito.verify(userMoviesRepository, times(1)).findAll();
}

huangapple
  • 本文由 发表于 2020年3月16日 09:44:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/60699415.html
匿名

发表评论

匿名网友

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

确定