3

I have the following post route in my REST controller:

 @RequestMapping(value = "", method = RequestMethod.POST, produces = "application/json") public ResponseEntity saveMovie(@RequestBody Movie movie){ movieService.saveMovie(movie); return new ResponseEntity<Movie>(movie, HttpStatus.OK); } 

The route uses a service to add the movie passed in request body in data store. The signature of the service method is this:

 Movie saveMovie(Movie movie); 

I have written the following test and a helper method for it:

 @Test public void saveMovie() throws Exception { Movie movie1 = new Movie(); movie1.setImdbID("imdb1"); movie1.setTitle("Meter"); movie1.setYear("2015"); movie1.setPoster("meter.jpg"); when(movieService.saveMovie(movie1)).thenReturn(movie1); mockMvc.perform(post("/v1/api/movie") .contentType(MediaType.APPLICATION_JSON_UTF8) .content(asJsonString(movie1)) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(content().contentType (MediaType.APPLICATION_JSON_UTF8_VALUE)); verify(movieService, times(1)).saveMovie(movie1); verifyNoMoreInteractions(movieService); } public static String asJsonString(final Object obj) { try { final ObjectMapper mapper = new ObjectMapper(); final String jsonContent = mapper.writeValueAsString(obj); System.out.println(jsonContent); return jsonContent; } catch (Exception e) { throw new RuntimeException(e); } } 

I get the following error:

 Argument(s) are different! Wanted: com.stackroute.ng2boot.service.MovieService#0 bean.saveMovie( com.stackroute.ng2boot.domain.Movie@ae372b9 ); -> at com.stackroute.ng2boot.controllers.MovieRestControllerTest. saveMovie(MovieRestControllerTest.java:129) Actual invocation has different arguments: com.stackroute.ng2boot.service.MovieService#0 bean.saveMovie( com.stackroute.ng2boot.domain.Movie@2098d37d ); -> at com.stackroute.ng2boot.controllers.MovieRestController. saveMovie(MovieRestController.java:60) 

Except save and update, where I need to pass a Movie JSON as request body, the other routs are passing tests. Please share your valuable inputs.

Thanks in advance.

0

3 Answers 3

1

Let's say this is the MovieService class:

@Component public class MovieService { private static List<Movie> movieList = new ArrayList<>(); static { Movie m1 = new Movie("id1", "title1","2000", "poster1.jpg"); Movie m2 = new Movie("id2", "title2","2001", "poster2.jpg"); Movie m3 = new Movie("id3", "title3","2002", "poster3.jpg"); Movie m4 = new Movie("id4", "title4","2003", "poster4.jpg"); Movie m5 = new Movie("id5", "title5","2004", "poster5.jpg"); movieList.add(m1); movieList.add(m2); movieList.add(m3); movieList.add(m4); movieList.add(m5); } public Movie saveMovie(Movie movie){ movieList.add(movie); return movie; } } 

And let's say this is the MovieController class:

@RestController public class MovieController { private final MovieService movieService; public MovieController(MovieService movieService) { this.movieService = movieService; } @PostMapping(value = "", produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity saveMovie(@RequestBody Movie movie){ movieService.saveMovie(movie); return new ResponseEntity<>(movie, HttpStatus.OK); } } 

You could write the test like below using MockMvc. The test checks if the HttpStatus in the response is the expected one: HttpStatus.OK. And also check if saveMovie.saveMovie was called once for movie6.

@RunWith(SpringRunner.class) @WebMvcTest(MovieController.class) public class MovieControllerTest { @Autowired private MockMvc mockMvc; @MockBean private MovieService movieService; @Test public void saveMovie() throws Exception { Movie movie6 = new Movie("id6", "title6", "2006", "poster6.jpg"); String movie6AsJson = new ObjectMapper().writeValueAsString(movie6); String url = "/"; when(movieService.saveMovie(any(Movie.class))).thenReturn(movie6); RequestBuilder requestBuilder = MockMvcRequestBuilders.post(url) .accept(MediaType.APPLICATION_JSON) .contentType(MediaType.APPLICATION_JSON) .content(movie6AsJson); MvcResult mvcResult = mockMvc.perform(requestBuilder).andReturn(); int actualResult = mvcResult.getResponse().getStatus(); int expectedResult = HttpStatus.OK.value(); assertEquals("Result not as expected!",expectedResult,actualResult); verify(movieService, times(1)).saveMovie(refEq(movie6)); } } 
Sign up to request clarification or add additional context in comments.

Comments

0

Can you try:

import static org.mockito.Matchers.refEq; ---- verify(movieService, times(1)).saveMovie(refEq(movie1)); 

Comments

0

You should try with:

verify(movieService).saveMovie(ArgumentMatchers.eq(movie1)); 

It would also be good to ensure that you have equals and hashCode methods implemented in Movie class.

Other small thing that I noticed (however, unrelated to your problem) is that you don't need to use both times(1) and verifyNoMoreInteractions(movieService). Mockito.verify is by default expected to be called once. Take look at it source:

public static <T> T verify(T mock) { return MOCKITO_CORE.verify(mock, times(1)); } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.