Я обрабатываю транзакции в 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);
});
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()
). Если это не макет, вы не можете записывать для него сопоставления и не можете определять заглушки для вызовов его методов.