Melye77 Melye77 - 6 months ago 11
Java Question

Mockito not working on update/create in RESTcontroller

I'm trying to write some tests using Mockito and I managed to write them for findAll and delete operations but for the create and update, they won't work.

@RunWith(MockitoJUnitRunner.class)
public class RentedControllerTest {

@Mock
private RentedService rentalService;

@Mock
private MovieService movieService;

@Mock
private ClientService clientService;

@InjectMocks
private RentedController rentalController;

@InjectMocks
private MovieController movieController;

@InjectMocks
private ClientController clientController;


@Before
public void setUp() throws Exception {
initMocks(this);
}

@Test
public void getMovies() throws Exception {
List<Movie> movies = new ArrayList<>();
movies.add(mock(Movie.class));
// System.out.println(movies.toString());
when(movieService.findAll()).thenReturn(movies);
//// System.out.println(movieService.findAll().toString());
MoviesDto response = movieController.getMovies();
assertEquals("should be 1 movie", 1, response.getMovies().size());
}

@Test
public void updateMovie() throws Exception {
Movie movie = new Movie(2,"Lotr",0, "dir2", 2003);
MovieDto movieDto = mock(MovieDto.class);
System.out.println(movie.toString());
when(movieService.updateMovie(anyInt(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(movie);
// Movie m = new Movie();
// m = movieService.updateMovie(2,"Lotrrrrr",0, "dir2", 2003);
// System.out.println(m.toString());
Map<String, MovieDto> map = movieController.updateMovie(2, movieDto);
System.out.println(map.toString());
assertEquals("Title should be Lots", "Lotr", map.get("movie").getName());
}

@Test
public void createMovie() throws Exception {
Movie movie = new Movie(2,"Lotr",0, "dir2", 2003);
MovieDto movieDto = mock(MovieDto.class);
when(movieService.createMovie(anyInt(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(movie);
Map<String, MovieDto> map = movieController.createMovie(movieDto);
assertEquals("Title should be Lotr", "Lotr", map.get("movie").getName());
}

@Test
public void deleteMovie() throws Exception {
ResponseEntity response = movieController.deleteMovie(1);
assertEquals("Http status should be OK", HttpStatus.OK, response.getStatusCode());
}
}


So the line "when(movieService.update....) work's just fine. I tested it with the write lines as you can see in the code and it works. The problem is here

Map<String, MovieDto> map = movieController.updateMovie(2, movieDto);


I gives me NullPointerException inside that method. The method looks like this:

@RequestMapping(value = "/movies/{movieId}", method = RequestMethod.PUT, consumes = CatalogMediaType.API_JSON)
public Map<String, MovieDto> updateMovie(@PathVariable final Integer movieId,
@RequestBody final MovieDto movieDto) {
log.trace("updateMovie: movieId={} movieDto={}", movieId, movieDto);

Movie movie = movieService.updateMovie(movieId, movieDto.getMovie().getName(), movieDto.getMovie().getNumberofrentals(), movieDto.getMovie().getDirector(), movieDto.getMovie().getYear());

Map<String, MovieDto> movieDtoMap = new HashMap<>();
movieDtoMap.put("movie", new MovieDto(movie));
log.trace("updateMovie: movieDtoMap={}", movieDtoMap);

return movieDtoMap;
}


The application itself works perfectly, the problem arises only when runing the mockito tests.

java.lang.NullPointerException
at ro.ubb.stcatalog.web.controller.MovieController.updateMovie(MovieController.java:41)
at ro.ubb.stcatalog.web.controller.RentedControllerTest.updateMovie(RentedControllerTest.java:82)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:119)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

2016-05-26T23:51:52,845 TRACE [main]: MovieController - createMovie: moviesDto=Mock for MovieDto, hashCode: 825249556

java.lang.NullPointerException
at ro.ubb.stcatalog.web.controller.MovieController.createMovie(MovieController.java:54)
at ro.ubb.stcatalog.web.controller.RentedControllerTest.createMovie(RentedControllerTest.java:92)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:119)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)


I don't really understand what the problem is if the findAll and delete work just fine... Any ideas?

Answer

I believe the mocking of MovieDto class is causing the NPE, as your controller is expecting a few params to be present in the DTO, which are not being set by the mock(), such as movieDto.getMovie().getName().

Create a MovieDto object from scratch with all the required params, or set the params post mocking, and you should be fine.

The following should work.

@Test
    public void updateMovie() throws Exception {
        Movie movie = new Movie(2,"Lotr",0, "dir2", 2003);
        MovieDto movieDto = mock(MovieDto.class);

        // Added the following line
        movieDto.setMovie(movie);

        System.out.println(movie.toString());
        when(movieService.updateMovie(anyInt(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(movie);
        Map<String, MovieDto> map = movieController.updateMovie(2, movieDto);
        System.out.println(map.toString());
        assertEquals("Title should be Lots", "Lotr", map.get("movie").getName());
    }