【问题标题】:JUnit 5 Unit test for JPAQueryJPAQuery 的 JUnit 5 单元测试
【发布时间】:2020-06-18 04:37:27
【问题描述】:

我一直在尝试找到一种方法来为以下函数编写一个简单的单元测试用例,但无法弄清楚任何事情。该函数基本上在 QueryDSL Q 类上使用 JPA Query,并将结果作为 Map 返回。任何示例代码就足够了。如何模拟整个 JPA 查询以返回 Map 。

@Autowired
EntityManager entityManager;
public Map<Integer, Double> getUsersCategoryAppliedBudgetMap(int opportunityTypeId, LocalDate startDate,
            LocalDate endDate) {
        QApplications applicationPath = QApplications.applications;
        JPAQuery<ApplicationApprovals> query = new JPAQuery<>(entityManager);
        log.info("Executing Budget Query for opportunity type" + opportunityTypeId);
        return query.from(applicationPath).where(applicationPath.applicationStatus.id
                .in(PENDING_APPROVAL.getId(), SENT_BACK.getId(), APPROVED.getId(), PENDING_WITHDRAW_APPROVAL.getId(),
                        PENDING_COMPLETION_DOCUMENT.getId(), REVIEW_COMPLETION_DOCUMENT.getId(), COMPLETED.getId())
                .and(applicationPath.opportunity.opportunityTypes.id.eq(opportunityTypeId))
                .and(applicationPath.appliedDate.between(startDate.atStartOfDay(), endDate.atTime(LocalTime.MAX))))
                .groupBy(applicationPath.user.id)
                .transform(GroupBy.groupBy(applicationPath.user.id).as(applicationPath.cost.sum()));
    }

【问题讨论】:

    标签: java mockito junit5 spring-test


    【解决方案1】:

    如果您使用的是 spring-boot 并且它是启动器并利用 Spring Data JPA 存储库,那么您可以尝试使用 @DataJpaTest 来设置内存中 H2 实例并针对该实例运行查询以检查您的代码。 Doc.

    【讨论】:

      【解决方案2】:

      您确定要进行 unit 测试吗? e.一个模拟你的持久层的测试?您究竟想通过该测试验证什么?

      [编辑:这最终是如何成为答案而不是评论的?]

      【讨论】:

      • 我想增加代码覆盖率,所以我必须写一个单元测试用例。
      • 会议指标是编写测试的错误动机。编写单元测试以保证合同的某个方面或重现、修复和记录错误!
      【解决方案3】:

      您可以连接提供JPAQuery 的接口,而不是调用new JPAQuery&lt;&gt;(entityManager); 的代码。然后你可以模拟这个接口,所以提供的 JPAQuery 是一个模拟,由你的测试控制。

      这是一个接口如何提供新对象的示例:

      @RequiredArgsConstructor
      public static class NewObject {
      
        private final Map<String, Integer> entries; //Equivalent of EntityManager in example above
        private final Function<Map<String, Integer>, Map<String, Integer>> mapSupplier; // new dependency, which supplies the new object to be mocked
      
        public Integer getKeyForValue(String key) {
          //rather than calling myMap = new HashMap<>(entries) use the method call
          //equivalent replacement of: JPAQuery<ApplicationApprovals> query = new JPAQuery<>(entityManager)
          Map<String, Integer> myMap = mapSupplier.apply(entries);
          return myMap.get(key);
        }
      }
      

      然后在您的测试中,您可以插入接口的替代实现,允许您提供要控制的对象的模拟:

      @Test
      public void valueReturnedFromNewObjectIsFromSuppliedMap() {
      
        //create a mock which will provide your new object
        Function<Map<String, Integer>, Map<String, Integer>> mockMapSupplier = mock(Function.class);
      
        //set up the object you want the mock to return
        Map<String, Integer> otherEntries = new HashMap<>();
        Integer alternativeValue = 1000;
        otherEntries.put(KEY, alternativeValue);
      
        //using Mockito, tell the mock when to return your expected response
        when(mockMapSupplier.apply(entries)).thenReturn(otherEntries);
      
        //create the class you want to test using your mock
        NewObject newObject = new NewObject(entries, mockMapSupplier);
      
        //verify it behaves as expected
        assertThat(newObject.getKeyForValue(KEY), is(alternativeValue));
      }
      

      以上示例使用 Mockito (https://site.mockito.org) 来提供可以在单元测试中控制的模拟对象。如果您不熟悉 Mockito,我建议您查看它们提供的文档和示例,以了解它的作用以及如何在测试中使用它来验证代码的行为。

      【讨论】:

      • 请举例,对不起,我没有按照你的代码进行操作
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-04-07
      • 1970-01-01
      • 2011-06-18
      • 2022-08-20
      • 2020-06-30
      • 2015-04-25
      • 1970-01-01
      相关资源
      最近更新 更多