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

omqzjyyz  于 2021-06-30  发布在  Java
关注(0)|答案(1)|浏览(318)

所以我对mockito的测试还很陌生,我查阅了一些教程,但是我理解的速度很慢。我有一个由ejb支持的端点。我想测试ejb中的方法。我尝试了这么多选项,显然我得到了一个nullpointer异常(我知道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());
  }
}
okxuctiv

okxuctiv1#

为了避免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种解决方案:
重构代码以引入一个执行借用工作流并返回模型的类,然后对该类进行单元测试
添加带有测试范围的jax-rs实现,例如jersey
由于不能单独用mockito模拟静态方法,因此可以尝试添加另一个测试库,例如powermockito,并模拟response静态方法调用。
对于解决方案2,可以添加以下maven依赖项:

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

相关问题