单元测试的问题是同一个集合在流和for循环中的处理方式不同。两种情况下的集合都是空的(data.size() = 0)
,但在第一种情况下,该集合以某种方式进行了处理,换句话说,它将进入for循环。在第二种情况下,该集合被跳过(这是意料之中的,因为它是空的)。
测试使用Mockito,Result<Record>
将用于JOOQ。
测试是旧的,没有变化,唯一的变化是从for循环到流。
案例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 for loop example截图
模拟的结果对象
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;
}```
1条答案
按热度按时间wqlqzqxt1#
为什么不起作用
你这是在嘲笑我
但是你没有嘲笑
Result.spliterator()
,或者至少我没有看到它,这就是Result.stream()
所称的,它只是Collection.stream()
:因此,您还必须模拟
spliterator()
方法,可能还需要模拟其他一些方法!或者,让Mockito调用default
方法:Can you make mockito (1.10.17) work with default methods in interfaces?
关于嘲笑的一般评论
我不相信模仿jOOQAPI是一个好主意。jOOQAPI是巨大的,你可能会忘记模仿这个或那个方法,正如这个问题所恰当地表明的。在你目前的设置下,你打算 * 每次 * 你计划一个新的专栏时 * 都更新你的模仿吗?例如,你正在这样做:
如果列被重命名了呢?或者另一个列被投影了呢?你必须更新这个测试。这感觉像是一件很麻烦的事,而且很容易出错。
虽然jOOQ本身有JDBC mocking capabilities,但请考虑该手册页上的粗体免责声明:
免责声明:使用这个jOOQAPI模拟JDBC连接的一般想法是使用一个非常简单的JDBC抽象来提供快速的解决方案、注入点等。(包括复杂的状态转换、事务、锁定等)。一旦您有此需求,请考虑使用实际的数据库产品进行集成测试,而不是在MockDataProvider内部实现测试数据库
在使用数据库时,通常最好采用运行集成测试的方法,有关详细信息,请参阅以下资源:
当然,如果您不信任jOOQ,您可以编写一些烟雾测试来确保jOOQ正常工作(jOOQ是一个外部依赖项)。但是jOOQ单元和集成测试是庞大的,所以一般来说,您应该能够信任像
Result
或Record
这样的核心类型来为您做正确的事情。您真正想要测试的是您的查询正确性,您只能针对实际数据库示例进行集成测试。