使用mockito模拟实体管理器并测试无状态EJB



所以我是mockito测试的新手,我查阅了一些教程,但理解起来很慢。我有一个由EJB支持的端点。我想测试EJB。我已经尝试了很多选项,显然我得到了一个空指针异常。(我知道nullpointer异常为(。模拟实体管理器不持久化对象。所以它给了我当我尝试对空列表执行任何操作时,出现空指针异常。请任何人都能出示我如何去做这件事,或者给我指任何详细的文章或教程,我可以阅读,以促进我的学习。谢谢伙计们。

这是我的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());
}
}

为了避免NullPointerException,您可以尝试在MovieHandlerTest类中添加以下代码:

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);
}

但是"Response.ok(borrow(.build(("出现了另一个问题

您有3种解决方案:

  1. 重构代码以引入一个执行借用工作流并返回模型的类,然后对该类进行单元测试
  2. 添加具有测试范围的JAX-RS实现,例如Jersey
  3. 由于不能单独使用Mockito来模拟静态方法,因此可以尝试添加另一个测试库,如PowerMockito,并模拟Repense静态方法调用

对于解决方案2,您可以添加以下maven依赖项:

<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>2.13</version>
<scope>test</scope>
</dependency>

最新更新