Можно ли делать строгие издевательства с Mockito?
Я хотел бы использовать строгие mocks, по крайней мере, при разработке в первый раз некоторых тестов против старого кода, поэтому любые методы, вызываемые в моем макете, генерируют исключение, если я не определял конкретные ожидания.
Из того, что я увидел, Mockito, если бы я не определил никаких ожиданий, просто вернет null, что позже вызовет исключение NullPointerException в другом месте.
Можно ли это сделать? Если да, то как?
Ответы
Ответ 1
Что вы хотите от этого сделать?
Вы можете установить для него значение RETURN_SMART_NULLS, которое позволяет избежать NPE и содержит некоторую полезную информацию.
Вы можете заменить это пользовательской реализацией, например, которая выдает исключение из метода answer
:
@Test
public void test() {
Object mock = Mockito.mock(Object.class, new NullPointerExceptionAnswer());
String s = mock.toString(); // Breaks here, as intended.
assertEquals("", s);
}
class NullPointerExceptionAnswer<T> implements Answer<T> {
@Override
public T answer(InvocationOnMock invocation) throws Throwable {
throw new NullPointerException();
}
}
Ответ 2
Вы можете использовать verifyNoMoreInteractions
. Это полезно, если проверенный класс ловит исключения.
@Test
public void testVerifyNoMoreInteractions() throws Exception {
final MyInterface mock = Mockito.mock(MyInterface.class);
new MyObject().doSomething(mock);
verifyNoMoreInteractions(mock); // throws exception
}
private static class MyObject {
public void doSomething(final MyInterface myInterface) {
try {
myInterface.doSomethingElse();
} catch (Exception e) {
// ignored
}
}
}
private static interface MyInterface {
void doSomethingElse();
}
Результат:
org.mockito.exceptions.verification.NoInteractionsWanted:
No interactions wanted here:
-> at hu.palacsint.CatchTest.testVerifyNoMoreInteractions(CatchTest.java:18)
But found this interaction:
-> at hu.palacsint.CatchTest$MyObject.doSomething(CatchTest.java:24)
Actually, above is the only interaction with this mock.
at hu.palacsint.stackoverflow.y2013.q8003278.CatchTest.testVerifyNoMoreInteractions(CatchTest.java:18)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
...
Ответ 3
Добавьте этот @Rule
в свой тестовый класс в качестве открытого поля:
@RunWith(JUnitParamsRunner.class)
public class MyClassTests {
@Rule
public MockitoRule mockito = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
@Test
....
}
Это значение было добавлено в Mockito в версии 2.3.0
.Из документации:
Обеспечивает чистые тесты, уменьшает дублирование тестового кода, улучшает debuggability. Предлагает лучшее сочетание гибкости и производительность. Настоятельно рекомендуется. Планируется по умолчанию для Mockito v3. Добавляет следующее поведение:
- Повышение производительности: тест не проходит рано, когда тестируется код вызывает метод-заглушку с разными аргументами (см. PotentialStubbingProblem).
- Чистые тесты без лишних заглушки: тест не пройден при наличии неиспользованных заглушек (см. UnnecessaryStubbingException).
- Более чистые, более СУХИЕ тесты ("Не повторяй" Себя "): если вы используете Mockito.verifyNoMoreInteractions(Object...), вы больше не нужно явно проверять заглушки. Они есть автоматически проверено для вас.
Ответ 4
Согласно исходному коду org.mockito.Mockito.RETURNS_DEFAULTS, он выбирает "что делать, если нет ожиданий" из глобальной настройки.
Кроме того, если глобальная конфигурация отсутствует, она использует {@link ReturnsEmptyValues} (возвращает нули, пустые коллекции, нули и т.д.) "
Я еще не смог выполнить эту конфигурацию.
Ответ 5
В дополнение к подходу MockitoRule
, если вам не нужно использовать конкретный тестовый прогон (а вы используете Mockito 2.5.1 или выше), вы также можете рассмотреть возможность использования MockitoJUnitRunner.StrictStubs
, т.е.
@RunWith(MockitoJUnitRunner.StrictStubs.class)
(я бы прокомментировал пост о MockitoRule, но пока не имею такой возможности)