簡體   English   中英

使用Mockito模擬實體管理器並測試無狀態EJB

[英]Using mockito to mock the entity manager and test a stateless 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,並模擬Reponse靜態方法調用。

對於解決方案2,您可以添加以下Maven依賴項:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM