堆栈社区您好,
我在验证模拟类方法的输入参数时遇到问题,因为结果显示它接受的输入值多于方法允许的值。我将尝试用下面的代码片段进行解释:
测试:
class MyClass {
//This is local class from project
@Mock
private ElasticSearchService elasticSearchService;
private final static String INDEX_NAME = "index-test";
private Consumer<Message<List<Command<Entity>>>> index;
@BeforeEach
void beforeEach() {
index = new EntityIndexFactory(elasticSearchService, new ObjectMapper()).create();
}
@Test
void happyCase() {
Event event = new Event();
event.setId("eventId");
event.setLastUpdate(1L);
Command<Entity> command = Command.builder()
.id(event.getId())
.type("event")
.version(event.getLastUpdate())
.actions(Map.of(INDEX_NAME, Action.UPSERT))
.source(event)
.build();
when(elasticSearchService.indexExists(any())).thenReturn(false);
index.accept(MessageBuilder.createMessage(List.of(command), new MessageHeaders(null)));
List<DocWriteRequest<?>> processDocs = new ArrayList<>();
processDocs.add(FactoryTestUtils.upsertRequest(INDEX_NAME, command));
verify(elasticSearchService).process(processDocs);
}
}
我要测试的课程:
@Service
@RequiredArgsConstructor
public class EntityIndexFactory {
@NonNull
private ElasticSearchService elasticSearchService;
@NonNull
private ObjectMapper objectMapper;
public <E extends Entity> Consumer<Message<List<Command<E>>>> create() {
return message -> {
try {
List<DocWriteRequest<?>> mappedCommands = message.getPayload().stream()
.map(this::mapCommand)
.flatMap(List::stream)
.toList();
elasticSearchService.process(mapSecondary(mappedCommands));
} catch (Exception e) {
throw new PersistenceException(e);
}
};
}
模拟课程:
@Service
@RequiredArgsConstructor
public class ElasticSearchService {
@NonNull
private RestHighLevelClient esClient;
public boolean process(List<DocWriteRequest<?>> requests) {
BulkRequest bulkRequest = new BulkRequest();
try {
requests.forEach(bulkRequest::add);
BulkResponse bulkResponse = esClient.bulk(bulkRequest, RequestOptions.DEFAULT);
boolean responseSuccess = !bulkResponse.hasFailures();
if (!responseSuccess) {
log.info("Failed to execute index operation : {}", bulkResponse.buildFailureMessage());
handleRetryableStatuses(bulkResponse);
}
return responseSuccess;
} catch (IOException ex) {
throw new RecoverableException("Exception caused during bulk execution", INFO_CODE, ex);
}
}
我在测试中从 VERIFY() 方法得到的参数不匹配:
注意:它显示的差异“indexExists() 是 ElasticSearchService 类中的另一个方法,在 EntityIndexorFactory 类中调用 mapSecondary() 期间调用。
我希望断言比较只会发生在 process() 方法输入参数上,该参数只是一个 List
编辑:添加了mapSecondary()方法以供调查参考。
private List<DocWriteRequest<?>> mapSecondary(List<DocWriteRequest<?>> esRequests) {
Map<String, Boolean> secondaryIndexExistence = new HashMap<>();
List<DocWriteRequest<?>> extendedList = new ArrayList<>(esRequests);
for (DocWriteRequest<?> request : esRequests) {
String index = request.index();
if (!secondaryIndexExistence.containsKey(index)) {
secondaryIndexExistence.put(index, elasticSearchService.indexExists(index + secondaryIndicesSuffix));
}
if (Boolean.TRUE.equals(secondaryIndexExistence.get(index))) {
if (request instanceof IndexRequest indexRequest) {
extendedList.add(secIndexUpsertRequest(indexRequest));
} else extendedList.add(secIndexDeleteRequest((DeleteRequest) request));
}
}
return extendedList;
}
我认为该屏幕截图代表“这就是我所期待的”和“这就是实际发生的情况”,即:它告诉您它正在等待一个呼叫,但收到了两个呼叫,这是正确的。
它并不期望
indexExists()
,因为那只是一个存根,并且 Mockito 会进行“很好的嘲笑”,您不必明确说出您的期望。它只是根据您设置的内容进行响应。这就是为什么你在左边只看到一种期望;因为你只设置了一个验证。但这两个电话都发生了,因此右边有两个。
仔细检查其他差异。您可能会发现不等式在列表中;
FactoryTestUtils.upsertRequest(INDEX_NAME, command)
实际上并不产生等于 mapSecondary(...)
结果的东西。
Mockito 使用对象的
equals()
方法来比较它们,因此如果您的 DocWriteRequest
没有实现该方法,则您的两个列表不相等,并且参数将不匹配。
有一些方法可以解决这个问题; 这个问题的答案,尤其是
ArgumentCaptor
,可能会对您有所帮助。