Используйте Mockito для проверки того, что после метода ничего не вызывается
Я использую Mockito для записи unit test в Java, и я хотел бы проверить, что определенный метод является последним, вызывающим объект.
Я делаю что-то подобное в тестируемом коде:
row.setSomething(value);
row.setSomethingElse(anotherValue);
row.editABunchMoreStuff();
row.saveToDatabase();
В моем макете меня не волнует порядок, в котором я редактирую все в строке, но очень важно, что я не пытаюсь сделать что-нибудь еще после того, как я его сохранил. Есть ли хороший способ сделать это?
Обратите внимание, что я не ищу подтвержденияNoMoreInteractions: он не подтверждает, что saveToDatabase - это последняя вызванная вещь, и она также терпит неудачу, если я вызываю что-либо в строке, которую я явно не проверяю. Я хотел бы сказать что-то вроде:
verify(row).setSomething(value);
verify(row).setSomethingElse(anotherValue);
verifyTheLastThingCalledOn(row).saveToDatabase();
Если это помогает, я перехожу к Mockito из теста JMock, который сделал это:
row.expects(once()).method("saveToDatabase").id("save");
row.expects(never()).method(ANYTHING).after("save");
Ответы
Ответ 1
Я думаю, что это требует больше пользовательской работы.
verify(row, new LastCall()).saveToDatabase();
а затем
public class LastCall implements VerificationMode {
public void verify(VerificationData data) {
List<Invocation> invocations = data.getAllInvocations();
InvocationMatcher matcher = data.getWanted();
Invocation invocation = invocations.get(invocations.size() - 1);
if (!matcher.matches(invocation)) throw new MockitoException("...");
}
}
Предыдущий ответ:
Вы правы. verifyNoMoreInteractions - это то, что вам нужно.
verify(row).setSomething(value);
verify(row).setSomethingElse(anotherValue);
verify(row).editABunchMoreStuff();
verify(row).saveToDatabase();
verifyNoMoreInteractions(row);
Ответ 2
Не на 100% по теме, но я просто искал, чтобы найти противоположность проверки, и это был единственный релевантный результат, он заканчивается тем, что я был после Mockito.verifyZeroInteractions(mock);
Просто покончим с кем-то другим, который ищет здесь...
Ответ 3
Этот вопрос привел меня к некоторым усовершенствованиям API проверки в JMockit (доступно в следующем выпуске 0.983).
Решение, с которым я столкнулся, позволяет вам написать (в тестовом методе):
new VerificationsInOrder() {{
unverifiedInvocations();
row.saveToDababase();
}};
... если вы хотите только проверить, что какой-то метод вызывается после всего остального. Чтобы проверить, что это происходит перед всеми другими вызовами, просто переместите вызов на верх. Это действительно относится к любой последовательности последовательных вызовов.
Если в дополнение к вышеуказанной проверке вы также хотите проверить, что некоторые другие методы вызывают в любом порядке, в тест может быть добавлен второй блок проверок (до или после другого блока это не имеет значения)
new Verifications() {{
row.setSomething(value);
row.setSomethingElse(anotherValue);
}};
Несмотря на то, что он немного длинный из-за использования анонимных внутренних классов, этот синтаксис является простым и гибким; обратите внимание, как он добавляет структуру к тесту и избегает повторения вызовов методов (например, verify(...)
). Это больше, чем описано здесь (Hamcrest matchers, invocation counts и т.д.), И это не ограничивается проверкой методов экземпляра (статические методы и конструкторы можно издеваться и проверять одинаково).