Issue
so i am new to testing with mockito and i have looked up a couple of tutorials but i'm pretty slow to understanding. I have an endpoint that is backed with an EJB. i want to test the methods in the EJB. I've tried so many options, apparently i get a nullpointer exception. (i know what a nullpointer exception is). the mocked entity manager does not persist the objects. so it gives me a null pointer exception when i try to perform any operation on an empty list. please anyone can show me how to go about this or point me to any detailed article or tutorial i could read to facilitate my learning. thanks Guys.
this is my ejb.
@Stateless
public class CustomerHandler {
@PersistenceContext
private EntityManager em;
public Response borrowMovie(List<RequestMovieDto> borrow) {
borrow.forEach(movies -> {
final Movie movie = findMovieByName(movies.getName());
movie.setAvailableCopies((movie.getAvailableCopies()) - movies.getAmount());
em.merge(movie);
});
return Response.ok(borrow).build();
}
public Movie findMovieByName(String name) {
return em.createQuery("SELECT m FROM Movie m "
+ "WHERE m.name = :name", Movie.class)
.setParameter("name", name)
.getSingleResult();
}
}
and this is my test class
@RunWith(MockitoJUnitRunner.class)
public class MovieHandlerTest {
@Mock
EntityManager manager;
private List<RequestMovieDto> request;
@InjectMocks
CustomerHandler handler;
@Before
public void setUp() {
final Movie first = new Movie();
first.setName("MISSION IMPOSSIBLE");
first.setAvailableCopies(10);
first.setIsbn("ABC788900");
manager.persist(first);
final Movie second = new Movie();
first.setName("JAMES BOND");
first.setAvailableCopies(10);
first.setIsbn("ABC788999");
manager.persist(second);
final Movie last = new Movie();
first.setName("HARRY POTTER");
first.setAvailableCopies(10);
first.setIsbn("ABC7882000");
manager.persist(last);
}
@Test
public void borrowMovie() {
RequestMovieDto first = new RequestMovieDto();
first.setName("MISSION IMPOSSIBLE");
first.setAmount(2);
RequestMovieDto second = new RequestMovieDto();
second.setName("JAMES BOND");
second.setAmount(1);
request = Arrays.asList(first, second);
final var response = handler.borrowMovie(request);
assertEquals(Response.Status.OK, response.getStatusInfo().toEnum());
}
}
Solution
To avoid the NullPointerException, you can try adding the following code in the MovieHandlerTest class:
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.when;
[..]
@Mock
EntityManager manager;
@Mock
TypedQuery<Movie> query;
[..]
@Before
public void setUp() {
final Movie first = new Movie();
first.setName("MISSION IMPOSSIBLE");
first.setAvailableCopies(10);
first.setIsbn("ABC788900");
final Movie second = new Movie();
first.setName("JAMES BOND");
first.setAvailableCopies(10);
first.setIsbn("ABC788999");
final Movie last = new Movie();
first.setName("HARRY POTTER");
first.setAvailableCopies(10);
first.setIsbn("ABC7882000");
when(manager.createQuery(any(String.class), eq(Movie.class))).thenReturn(query);
when(query.setParameter(any(String.class), any(String.class))).thenReturn(query);
when(query.getSingleResult()).thenReturn(first, second, last);
}
But another problem arises with "Response.ok(borrow).build()"
You have 3 solutions:
- Refactor the code to introduce a class that executes the borrowing workflow and returns a model, then unit test this class
- Add a JAX-RS implementation with a test scope, such as Jersey
- Since you can't mock static methods with Mockito alone, you can try adding another testing library, such as PowerMockito, and mock the Reponse static method calls.
For solution 2, you can add the following maven dependency:
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>2.13</version>
<scope>test</scope>
</dependency>
Answered By - Soufiane Sakhi
Answer Checked By - David Marino (JavaFixing Volunteer)