Mockito 验证显示的输入值多于方法允许的值

问题描述 投票:0回答:1

堆栈社区您好,

我在验证模拟类方法的输入参数时遇到问题,因为结果显示它接受的输入值多于方法允许的值。我将尝试用下面的代码片段进行解释:

测试:

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() 期间调用。

图片: Argument mismatch

我希望断言比较只会发生在 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;

}
java mockito verify
1个回答
0
投票

我认为该屏幕截图代表“这就是我所期待的”和“这就是实际发生的情况”,即:它告诉您它正在等待一个呼叫,但收到了两个呼叫,这是正确的。

它并不期望

indexExists()
,因为那只是一个存根,并且 Mockito 会进行“很好的嘲笑”,您不必明确说出您的期望。它只是根据您设置的内容进行响应。这就是为什么你在左边只看到一种期望;因为你只设置了一个验证。但这两个电话都发生了,因此右边有两个。

仔细检查其他差异。您可能会发现不等式在列表中;

FactoryTestUtils.upsertRequest(INDEX_NAME, command)
实际上并不产生等于
mapSecondary(...)
结果的东西。

Mockito 使用对象的

equals()
方法来比较它们,因此如果您的
DocWriteRequest
没有实现该方法,则您的两个列表不相等,并且参数将不匹配。

有一些方法可以解决这个问题; 这个问题的答案,尤其是

ArgumentCaptor
,可能会对您有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.