首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >单元测试:集合正在使用for-循环处理,但不使用流处理。

单元测试:集合正在使用for-循环处理,但不使用流处理。
EN

Stack Overflow用户
提问于 2022-08-23 09:21:00
回答 1查看 1K关注 0票数 9

单元测试的问题是相同的集合在流和for循环中被不同的处理。这两种情况下的集合都是空的(data.size() = 0),但在例1中,集合是以某种方式处理的,换句话说,它将执行for-循环。在第2种情况下,该集合被跳过(因为它是空的)。

测试使用的是Mockito,而Result<Record>正在开始使用JOOQ。

测试是旧的,不变的,唯一的改变是从一个循环到另一个流。

案例1

代码语言:javascript
运行
复制
private SearchResult iterateData(
      Result<Record> data, ...) {

      for (Record record : data) {
           doSomething(record);
    }

案例2

代码语言:javascript
运行
复制
private SearchResult iterateData(
      Result<Record> data, ...) {
      data.stream().forEach(record -> doSomething(record)); 

案例1 循环示例的屏幕截图

模拟结果对象

代码语言:javascript
运行
复制
private DefaultSearchRequestModel rowSpecificValuesTestSetup(
      parameters...) {
    

    DefaultSearchRequestModel searchRequest = new DefaultSearchRequestModel(
        Arrays.asList(....),
        Collections.singletonList(
            new SearchFilter(
                "test",
                Collections.singletonList(...)));

    List<Column> columns =
        this.searchService.filterUserAllowedColumns(...);

    Condition searchCondition =
        this.searchRepositoryMock.getSearchConditions(...);

    List<TableJoinMapping> joinMappings = ColumnHelper.getColumnTranslateDeviceJoinMappings(
        columns,
        searchRequest.getFilters());

    Result<Record> deviceDataResultMock = Mockito.mock(Result.class);
    Iterator<Record> resultIterator = Mockito.mock(Iterator.class);
    final Table fromTableMock = Mockito.mock(Table.class);
    when(resultIterator.hasNext()).thenReturn(true, false);
    Record recordMock = Mockito.mock(Record.class);
    when(resultIterator.next()).thenReturn(recordMock);
    when(deviceDataResultMock.iterator()).thenReturn(resultIterator);
    when(recordMock.get(CONTRACTID)).thenReturn(contractId);
   ...
when(this.userPermissions.getAccessPermissions()).thenReturn(searchRequest.getColumns().stream().map
        (name -> Column.findByName(name).getId()).collect(
        Collectors.toList()));
    when(this.searchRepositoryMock.getCurrentTable(companyId))
        .thenReturn(fromTableMock);
    when(recordMock.get(TYPEID)).thenReturn(financialTypeId);
    when(this.searchRepositoryMock.getDeviceData(
        ArgumentMatchers.anyList(),
        ArgumentMatchers.anyList(),
        any(),
        any(),
        eq(searchRequest.getPageSize()),
        eq(searchRequest.getPage()),
        eq(searchRequest.getSortCriterias()),
        eq(fromTableMock),
        ArgumentMatchers.anyList(),
        eq(Optional.empty()),
        eq(this.dslContextMock)))
        .thenReturn(deviceDataResultMock);

    return searchRequest;
  }```
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-08-24 08:18:11

为什么它不起作用

你在嘲笑Result.iterator()

代码语言:javascript
运行
复制
when(deviceDataResultMock.iterator()).thenReturn(resultIterator);

但是你没有嘲笑Result.spliterator(),或者至少我没有看到它,这就是Result.stream()所调用的,也就是Collection.stream()

代码语言:javascript
运行
复制
default Stream<E> stream() {
    return StreamSupport.stream(spliterator(), false);
}

因此,您还必须模拟spliterator()方法,可能还有其他几个方法!或者,告诉Mockito调用default方法:

您能让mockito (1.10.17)在接口中使用默认方法吗?

论总体上的嘲弄

我不相信嘲笑jOOQ API是一个非常好的主意。jOOQ API非常庞大,您可能会忘记模拟这个或那个方法,这里的问题恰当地说明了这一点。使用当前的设置,您计划在每次生成新列时更新模拟吗?例如,你要这样做:

代码语言:javascript
运行
复制
when(recordMock.get(DEVICEID.getName()).thenReturn(deviceId);

如果该列被重命名怎么办?或者是另一列的投影?你必须更新这个测试。这感觉很烦人,而且很容易出错。

虽然jOOQ本身有JDBC模拟功能,但请考虑手册页上的粗体免责声明:

免责声明:使用这个JDBC来模拟jOOQ连接的一般想法是使用一个非常简单的JDBC提供快速的解决方案、注入点等等。不建议模拟整个数据库(包括复杂的状态转换、事务、锁定等)。使用这个模拟API。一旦有了这个需求,请考虑使用实际的数据库产品来进行集成测试,而不是在MockDataProvider中实现您的测试数据库。

在使用数据库时,通常最好使用运行集成测试,有关一些详细信息,请参阅以下资源:

当然,您可以编写一些冒烟测试,以确保jOOQ在不信任jOOQ (jOOQ是外部依赖项)的情况下正确工作。但是jOOQ单元和集成测试是庞大的,所以一般来说,您应该能够信任ResultRecord这样的核心类型来为您做正确的事情。您真正想要测试的是您的查询正确性,而且您只能对一个实际的数据库实例进行集成测试。

票数 19
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73456148

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档