Издевающийся объект, вызываемый в лямбда-выражении, вызванный из издевающегося объекта

Я обрабатываю транзакции в Spring boot 2.7 вручную:

dataHeader = transactionTemplate.execute(status -> {
    final var doc = findDoc(document);
    return saveReport(doc);
});

private Doc findDoc(DocumentDto document) {
    return docRepository.findByDocType(document.getType(), document.getId()), document.getReport()).get(0);
}

Я нашел этот ответ горячим для проверки такого случая, поэтому написал следующее:

when(docRepository.findByDocType(any(), any(), any())).thenReturn(List.of());
when(transactionTemplate.execute(any(TransactionCallback.class)))
        .then(invocation -> ((TransactionCallback<Doc>) invocation.getArgument(0))
                .doInTransaction(any(TransactionStatus.class)));

var log = LoggerWithMemoryFactory.getBufferedLoggerApi(DocService.class);
final var actual = logEvent.getMessage().getStringPayload();
if (!actual.contains(expected)) {
    var message = String.format("expected: '%s' in '%s'", expected, actual);
    throw new AssertionFailedError(message, expected, actual);
}

AFAIK Я не смешиваю какие-либо сопоставления () со значениями (например, «X» или 10L). Но мой тест все равно не удался из-за неправильного количества совпадений для docRepository.findByDocType.

org.mockito.exceptions.misusing.InvalidUseOfMatchersException: 
Invalid use of argument matchers! 3 matchers expected, 1 recorded

Ради любопытства, это хорошо работает в отладчике, когда я ставлю точку останова перед docRepository.findByDocType.

Я нашел этот билет Mockito, который выглядит актуальным, но я не понял его и не знаю, как применить его к моей ситуации.

Когда я взял из лямбды код, использующий имитируемый объект, тест работает хорошо:

final var doc = docRepository.findByDocType(document.getType(), document.getId()), document.getReport()).get(0);
dataHeader = transactionTemplate.execute(status -> {
    return saveReport(doc);
});
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
82
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

AFAIK, я не смешиваю какие-либо сопоставления () со значениями (например, «X» или 10L)

Нет, но вы помещаете Matchers в стек Mockito вне вызова when:

when(transactionTemplate.execute(any(TransactionCallback.class)))
        .then(invocation -> invocation.<TransactionCallback<Doc>>getArgument(0)
                .doInTransaction(any(TransactionStatus.class)));
                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ you must not use a matcher when calling a method

Что вы ожидаете от этого кода? .doInTransaction(any(…)) не имеет никакого смысла (и any(…) просто выполняет return null после того, как совпадение было записано). Попробуйте (в отдельном тесте):

assertNull(any(TransactionStatus.class));

Вы должны вызвать метод с реальным аргументом (но если вы не используете status, то null тоже может сработать).

Кроме того, transactionTemplate ДОЛЖЕН быть макетом объекта Mockito (@Mock, Mockito.mock(), @Spy или Mockito.spy()). Если это не макет, вы не можете записывать для него сопоставления и не можете определять заглушки для вызовов его методов.

Другие вопросы по теме

SemanticException: элемент выбора в позиции 1 в списке выбора не имеет псевдонима при использовании подвыбора JPQL
Как сопоставить тип базы данных массива с Kotlin
Не удалось найти валидатор для ограничения «jakarta.validation.constraints.Pattern» — ошибка все еще появляется даже после удаления валидатора из класса
Как я могу разрешить JpaRepository <> в Spring MVC
Spring Data JPA/Hibernate: выражения конструктора JPQL - разница между использованием «нового (..)» и его неиспользованием
Ошибка создания bean-компонента с именем «entityManagerFactory» при обновлении приложения до Spring boot 3.3.0
Должен ли я применить @Transactional(readOnly = true) к простому методу запроса?
Обновление Spring Boot JPA с использованием составных первичных ключей
Не удалось безопасно определить назначение хранилища для интерфейса-кандидата репозитория, даже если объект помечен с помощью jakarta.persistence.Entity
JPQL, как присоединиться к выборке списка с любым условием соответствия списку