单元测试的问题是相同的集合在流和for循环中被不同的处理。这两种情况下的集合都是空的(data.size() = 0)
,但在例1中,集合是以某种方式处理的,换句话说,它将执行for-循环。在第2种情况下,该集合被跳过(因为它是空的)。
测试使用的是Mockito,而Result<Record>
正在开始使用JOOQ。
测试是旧的,不变的,唯一的改变是从一个循环到另一个流。
案例1
private SearchResult iterateData(
Result<Record> data, ...) {
for (Record record : data) {
doSomething(record);
}
案例2
private SearchResult iterateData(
Result<Record> data, ...) {
data.stream().forEach(record -> doSomething(record));
案例1 循环示例的屏幕截图
模拟结果对象
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;
}```
发布于 2022-08-24 08:18:11
为什么它不起作用
你在嘲笑Result.iterator()
when(deviceDataResultMock.iterator()).thenReturn(resultIterator);
但是你没有嘲笑Result.spliterator()
,或者至少我没有看到它,这就是Result.stream()
所调用的,也就是Collection.stream()
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
因此,您还必须模拟spliterator()
方法,可能还有其他几个方法!或者,告诉Mockito调用default
方法:
您能让mockito (1.10.17)在接口中使用默认方法吗?
论总体上的嘲弄
我不相信嘲笑jOOQ API是一个非常好的主意。jOOQ API非常庞大,您可能会忘记模拟这个或那个方法,这里的问题恰当地说明了这一点。使用当前的设置,您计划在每次生成新列时更新模拟吗?例如,你要这样做:
when(recordMock.get(DEVICEID.getName()).thenReturn(deviceId);
如果该列被重命名怎么办?或者是另一列的投影?你必须更新这个测试。这感觉很烦人,而且很容易出错。
虽然jOOQ本身有JDBC模拟功能,但请考虑手册页上的粗体免责声明:
免责声明:使用这个JDBC来模拟jOOQ连接的一般想法是使用一个非常简单的JDBC提供快速的解决方案、注入点等等。不建议模拟整个数据库(包括复杂的状态转换、事务、锁定等)。使用这个模拟API。一旦有了这个需求,请考虑使用实际的数据库产品来进行集成测试,而不是在MockDataProvider中实现您的测试数据库。
在使用数据库时,通常最好使用运行集成测试,有关一些详细信息,请参阅以下资源:
当然,您可以编写一些冒烟测试,以确保jOOQ在不信任jOOQ (jOOQ是外部依赖项)的情况下正确工作。但是jOOQ单元和集成测试是庞大的,所以一般来说,您应该能够信任Result
或Record
这样的核心类型来为您做正确的事情。您真正想要测试的是您的查询正确性,而且您只能对一个实际的数据库实例进行集成测试。
https://stackoverflow.com/questions/73456148
复制相似问题