Mockito - как проверить, что макет никогда не вызывался
Я ищу способ проверить с Mockito, что не было никакого взаимодействия с данным макетом во время теста. Легко добиться этого для данного метода с режимом проверки never()
, но я еще не нашел решение для полного макета.
То, что я действительно хочу достичь: проверьте в тестах, что ничего не печатается на консоли. Общая идея с jUnit выглядит следующим образом:
private PrintStream systemOut;
@Before
public void setUp() {
// spy on System.out
systemOut = spy(System.out);
}
@After
public void tearDown() {
verify(systemOut, never()); // <-- that doesn't work, just shows the intention
}
A PrintStream
имеет множество методов, и я действительно не хочу проверять каждую отдельную проверку - и то же самое для System.err
...
Поэтому я надеюсь, что если это будет простое решение, которое я могу, учитывая, что у меня есть хорошее покрытие для тестирования, заставьте инженеров-программистов (и меня) удалить их (мой) код отладки, например System.out.println("Breakpoint#1");
или e.printStacktrace();
до совершения изменений.
Ответы
Ответ 1
Используйте это:
import static org.mockito.Mockito.verifyZeroInteractions;
// ...
private PrintStream backup = System.out;
@Before
public void setUp() {
System.setOut(mock(PrintStream.class));
}
@After
public void tearDown() {
verifyZeroInteractions(System.out);
System.setOut(backup);
}
Ответ 2
verifyZeroInteractions(systemOut);
Как отмечено в комментариях, это не работает со шпионом.
Для грубо эквивалентного, но более полного ответа см. ответ gontard на этот вопрос.
Ответ 3
Вы можете попробовать немного другое:
private PrintStream stdout;
@Before public void before() {
stdout = System.out;
OutputStream out = new OutputStream() {
@Override public void write(int arg0) throws IOException {
throw new RuntimeException("Not allowed");
}
};
System.setOut(new PrintStream(out));
}
@After public void after() {
System.setOut(stdout);
}
Если вы предпочитаете, вы можете переключить анонимный тип для макета и проверить как предлагает Don Roby.
Ответ 4
Один из способов решения этой проблемы - реорганизовать тестируемый класс, чтобы можно было использовать PrintStream, который можно использовать для вывода. Это позволит вам unit test, не полагаясь на поведение класса System
. Вы можете использовать конструктор private-package для этой инъекции, поскольку вы будете использовать его только из соответствующего тестового класса. Так что это может выглядеть примерно так.
public class MyClass{
private PrintWriter systemOut;
public MyClass(){
this(System.out);
}
MyClass(PrintWriter systemOut){
this.systemOut = systemOut;
// ...any other initialisation processing that you need to do
}
}
и внутри самого класса используйте переменную systemOut вместо System.out, где вы вызываете ее.
Теперь, в пределах тестового класса, создайте mock PrintStream
и передайте его конструктору private-private, чтобы получить объект, который вы собираетесь тестировать. Теперь вы можете запускать любые действия, которые вам нравятся из ваших тестов, и использовать verify
для проверки их эффектов на ваш макет PrintStream
.