Как замокировать методы с возвращаемым типом void с помощью Mockito
Как замокировать методы с возвращаемым типом void?
Я реализовал паттерн наблюдатель, но не могу замокировать его с помощью Mockito, потому что не знаю, как это сделать.
Я пытался найти пример в интернете, но не смог.
Мой класс выглядит следующим образом:
public class World {
List<Listener> listeners;
void addListener(Listener item) {
listeners.add(item);
}
void doAction(Action goal, Object obj) {
setState("я получил");
goal.doAction(obj);
setState("я закончил");
}
private String state;
// сеттер и геттер для state
}
public class WorldTest implements Listener {
@Test public void word() {
World w = mock(World.class);
w.addListener(this);
...
...
}
}
interface Listener {
void doAction();
}
Система не вызывается с мок-объектом.
Я хочу отобразить состояние вышеупомянутой системы и сделать утверждения в соответствии с ними.
5 ответ(ов)
Я думаю, что нашёл более простой ответ на этот вопрос. Чтобы вызвать реальный метод для одного конкретного метода (даже если он имеет возвращаемое значение void
), вы можете сделать так:
Mockito.doCallRealMethod().when(<objectInstance>).<method>();
<objectInstance>.<method>();
Или, если вы хотите вызывать реальные методы для всех методов этого класса, можно сделать следующее:
<Object> <objectInstance> = mock(<Object>.class, Mockito.CALLS_REAL_METHODS);
Добавляя к тому, что сказал @sateesh, если вам нужно замокировать метод без возвращаемого значения (void), чтобы предотвратить его вызов в тесте, вы можете использовать Spy
следующим образом:
World world = new World();
World spy = Mockito.spy(world);
Mockito.doNothing().when(spy).methodToMock();
Когда вы будете запускать свой тест, убедитесь, что метод вызывается на объекте spy
, а не на объекте world
. Например:
assertEquals(0, spy.methodToTestThatShouldReturnZero());
Таким образом, вы сможете контролировать поведение метода, не выполняя его фактическую реализацию во время тестирования.
Во-первых, всегда импортируйте статические методы Mockito, так ваш код будет гораздо более читаемым и интуитивно понятным:
import static org.mockito.Mockito.*;
Для частичного мокирования, сохраняя при этом оригинальную функциональность, Mockito предлагает использовать "Spy".
Вы можете сделать это следующим образом:
private World world = spy(new World());
Чтобы предотвратить выполнение определенного метода, вы можете использовать что-то вроде этого:
doNothing().when(someObject).someMethod(anyObject());
Для добавления кастомного поведения к методу используйте "when" с "thenReturn":
doReturn("something").when(this.world).someMethod(anyObject());
Для получения дополнительных примеров, пожалуйста, ознакомьтесь с отличными примерами Mockito в документации.
В Java 8 это можно сделать чуть чище, если вы используете статический импорт для org.mockito.Mockito.doAnswer
:
doAnswer(i -> {
// Здесь выполняем действия с i.getArguments()
return null;
}).when(*mock*).*method*(*methodArguments*);
Важно, чтобы return null;
присутствовал, так как без него компиляция завершится с довольно неясными ошибками, поскольку компилятор не сможет найти подходящий переопределяемый метод для doAnswer
.
Например, интерфейс ExecutorService
, который просто немедленно выполняет любой Runnable
, переданный в метод execute()
, можно реализовать следующим образом:
doAnswer(i -> {
((Runnable) i.getArguments()[0]).run();
return null;
}).when(executor).execute(any());
Я думаю, что ваши проблемы связаны со структурой тестов. Мне сложно совмещать моки с традиционным методом реализации интерфейсов в тестовом классе, как вы сделали здесь.
Если вы реализуете слушателя как мок, вы сможете проверить взаимодействие.
Listener listener = mock(Listener.class);
w.addListener(listener);
world.doAction(..);
verify(listener).doAction();
Это должно подтвердить, что 'World' выполняет правильные действия.
Как проверить, что конкретный метод не был вызван, используя Mockito?
Как протестировать класс с приватными методами, полями или внутренними классами?
"Как сделать так, чтобы имитируемый метод возвращал аргумент, который был ему передан?"
Как установить Java 8 на Mac
Что значит 'synchronized'?