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

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

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&lt;Movies, Integer&gt; {
}

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 = &quot;/movies&quot;)
public  List&lt;Movies&gt; movies(){
List&lt;Movies&gt; allMovies = (List&lt;Movies&gt;) moviesRepository.findAll();
if (!allMovies.isEmpty()){
return allMovies;
} else {
throw new ResponseStatusException(
HttpStatus.NOT_FOUND, &quot;Movies not found&quot;
);
}
}
//    @CrossOrigin
//    @RequestMapping(path = &quot;movies/user/{id}&quot;)
//    public List&lt;Movies&gt; movie(@PathVariable(&quot;id&quot;) int id){
//        return this.movies().stream().map(movie -&gt; {
//            Users[] user = restTemplate.getForObject(&quot;http://127.0.0.1:8082/users/&quot; + id, Users[].class);
//            return new Movies(movie.getMovieId(), movie.getMovieName(), &quot;Description&quot;);
//        })
//                .collect(Collectors.toList());
//    }
@CrossOrigin
@GetMapping(path=&quot;/movie/{id}&quot;)
public  Movies getMovie(@PathVariable Integer id){
return moviesRepository.findById(id)
.orElseThrow(() -&gt; new ResponseStatusException(
HttpStatus.NOT_FOUND, &quot;Movie not found&quot;
) );
}
@CrossOrigin
@DeleteMapping(&quot;/movie/delete/{id}&quot;)
void deleteMovie(@PathVariable Integer id) {
moviesRepository.deleteById(id);
}
@CrossOrigin
@PutMapping(&quot;/movie/update/{id}&quot;)
Movies updateMovie(@RequestBody Movies updateMovie, @PathVariable Integer id) {
return moviesRepository.findById(id)
.map(Movies -&gt; {
Movies.setMovieName(updateMovie.getMovieName());
Movies.setMovieDescription(updateMovie.getMovieDescription());
return moviesRepository.save(Movies);
})
.orElseGet(() -&gt; {
updateMovie.setMovieId(id);
return moviesRepository.save(updateMovie);
});
}
@CrossOrigin
@PostMapping(path=&quot;/newMovie&quot;)
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&lt;Movies&gt; moviesList = new ArrayList&lt;Movies&gt;();
moviesList.add(new Movies(1, &quot;Star Wars&quot;, &quot;A New Hope&quot;));
moviesList.add(new Movies(2, &quot;Star Wars&quot;, &quot;Empire Strikes Back&quot;));
when(moviesRepository.findAll()).thenReturn(moviesList);
mockMvc.perform(get(&quot;/movies&quot;))
.andExpect(status().isOk())
.andExpect(jsonPath(&quot;$&quot;, hasSize(2)))
.andExpect(jsonPath(&quot;$[0].movieName&quot;, is(&quot;Star Wars&quot;)))
.andExpect(jsonPath(&quot;$[0].movieDescription&quot;, is(&quot;A New Hope&quot;)))
.andExpect(jsonPath(&quot;$[1].movieName&quot;, is(&quot;Star Wars&quot;)))
.andExpect(jsonPath(&quot;$[1].movieDescription&quot;, is(&quot;Empire Strikes Back&quot;)));
Mockito.verify(moviesRepository, times(1)).findAll();
}
}

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

java.lang.AssertionError: JSON path &quot;$&quot;
Expected: a collection with size &lt;2&gt;
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

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

@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.

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

发表评论

匿名网友

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

确定