我正在寻找一种方法来验证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
}
PrintStream
有很多方法,我真的不想用单独的验证验证每一个方法 - System.err
也是如此......
所以我希望,如果有一个简单的解决方案,我可以,鉴于我有一个很好的测试覆盖率,强迫软件工程师(和我自己)删除他们的(我的)调试代码,如System.out.println("Breakpoint#1");
或{在提交更改之前{1}}。
答案 0 :(得分:59)
使用此:
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);
}
答案 1 :(得分:11)
verifyZeroInteractions(systemOut);
如评论中所述,这不适用于间谍。
对于大致相当但更完整的答案,请参阅gontard对此问题的回答。
答案 2 :(得分:4)
您可以尝试稍微不同的方法:
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);
}
如果您愿意,可以为模拟切换匿名类型并验证as Don Roby suggests。
答案 3 :(得分:2)
解决此问题的一种方法是重构您正在测试的类,以允许注入可用于输出的PrintStream。这将允许您对其进行单元测试,而不依赖于System
类的行为。您可以使用package-private构造函数进行此注入,因为您只能从相应的测试类中使用它。所以它可能看起来像这样。
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,只要你调用后者。
现在,在测试类中,创建一个模拟PrintStream
,并将其传递给package-private构造函数,以获取您要测试的对象。现在,您可以在测试中运行您喜欢的任何操作,并使用verify
检查它们对模拟PrintStream
的影响。
答案 4 :(得分:2)
由于最初的正确答案verifyZeroInteractions
已过时,请改用verifyNoInteractions
:
import org.junit.jupiter.api.Test;
import static org.mockito.Mockito.*;
public class SOExample {
@Test
public void test() {
Object mock = mock(Object.class);
verifyNoInteractions(mock);
}
}