【问题标题】:Mockito Mock Entity Manger doesn't work properlyMockito 模拟实体管理器无法正常工作
【发布时间】:2021-09-19 20:43:07
【问题描述】:

我在下面提供了示例代码。但是当测试运行时,它会调用数据库来获取数据并从数据库中获取数据。 为什么模拟不能正常工作?如何避免在这些类型的服务中调用数据库?

端点:/v1/reservations/calculate-price-by-id/{reservation_id}

服务层

public Object getPrice(Long reservation_id){
    String stringQuery = "SELECT distinct u FROM Reservation u left join fetch u.driverAssignment  where u.id=:reservation_id";
    Query query = em.createQuery(stringQuery);
    query.setParameter("reservation_id", reservation_id);
    List<Reservation> reservations = query.getResultList();
    if(reservations.size()==0)
        return new DefaultResponseDTO(201, ResponseStatus.INVALID_INPUTS, "Reservation Id Not valid");

    return new DefaultResponseDTO(200, ResponseStatus.OK, "Price Calculated.", reservations );
}

单元测试

@Test
@DisplayName("Get prices of a reservation by it's id")
void getPaymentById() throws Exception {

   List<Reservation> list = new LinkedList<>();
   Query queryByMock =  Mockito.mock(TypedQuery.class);
   String stringQuery = "SELECT distinct u FROM Reservation u left join fetch u.driverAssignment  where u.id=:reservation_id";
   Mockito.when(em.createQuery(stringQuery)).thenReturn(queryByMock);
   Mockito.when(queryByMock.getResultList()).thenReturn(list);

   mockMvc.perform(MockMvcRequestBuilders
           .get("/v1/reservations/calculate-price-by-id/1").contentType(MediaType.APPLICATION_JSON_VALUE))
           .andExpect(status().isOk())
           .andExpect(jsonPath("$.code", is(200)))
           .andExpect(jsonPath("$.data",hasSize(3)));
}

【问题讨论】:

    标签: spring-boot mockito junit5


    【解决方案1】:

    现在您正在模拟使用 stringQuery 调用的 createQuery。您可能想要更改它并基本上接受任何字符串。请尝试以下操作:

    @Test
    @DisplayName("Get prices of a reservation by it's id")
    void getPaymentById() throws Exception {
    
       List<Reservation> list = new LinkedList<>();
       Query queryByMock = Mockito.mock(Query.class);
       String stringQuery = "SELECT distinct u FROM Reservation u left join fetch u.driverAssignment  where u.id=:reservation_id";
       Mockito.when(em.createQuery(anyString())).thenReturn(queryByMock);
       Mockito.when(queryByMock.getResultList()).thenReturn(list);
    
       mockMvc.perform(MockMvcRequestBuilders
               .get("/v1/reservations/calculate-price-by-id/1").contentType(MediaType.APPLICATION_JSON_VALUE))
               .andExpect(status().isOk())
               .andExpect(jsonPath("$.code", is(200)))
               .andExpect(jsonPath("$.data",hasSize(3)));
    }
    

    不过,这只有在单元测试设置期间在服务中注入 EntityManager 模拟 em 时才有效。请确保您这样做。

    【讨论】:

    • 我尝试了anyString(),但它也对我不起作用。如果同一方法中有两个查询字符串,我们不能使用anyString()。我将 EntityManager 注入为@MockBean private EntityManager em
    • 是的,你不能,但在你的例子中没有两个字符串,只有一个。您能否包括完整的测试类,以便我们检查您还有什么?这应该是集成测试吗?
    • 我已经编辑了我的答案。我更改了Query queryByMock = Mockito.mock(Query.class); 行。原因是 EntityManager.createQuery(String) 方法返回 Query 而不是 TypedQuery
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-14
    • 2015-09-27
    • 1970-01-01
    • 2016-01-25
    • 2018-04-08
    • 2015-06-28
    • 2016-06-04
    相关资源
    最近更新 更多