65

我正在寻找一种使用 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
}

APrintStream有很多方法,我真的不想用单独的验证来验证每一个方法——对于System.err......

所以我希望,如果有一个简单的解决方案,我可以,考虑到我有很好的测试覆盖率,强制软件工程师(和我自己)在提交更改之前System.out.println("Breakpoint#1");或之前删除他们的(我的)调试代码。e.printStacktrace();

4

5 回答 5

82

用这个 :

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);
}
于 2012-08-13T15:10:53.623 回答
13
verifyZeroInteractions(systemOut);

如评论中所述,这不适用于间谍。

有关大致等效但更完整的答案,请参阅 gontard 对此问题的回答。

于 2012-08-13T14:28:08.637 回答
10

由于原始正确答案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);
    }
}
于 2020-02-12T23:40:42.217 回答
5

您可以尝试稍微不同的方法:

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 的建议进行验证。

于 2012-08-13T14:52:00.807 回答
2

解决此问题的一种方法是重构您正在测试的类,以允许注入可用于输出的 PrintStream。这将让您对它进行单元测试,而不依赖于System类的行为。您可以为此注入使用包私有构造函数,因为您只会在相应的测试类中使用它。所以它可能看起来像这样。

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。

现在,在测试类中,创建一个 mockPrintStream并将其传递给 package-private 构造函数,以获取您要测试的对象。现在,您可以从测试中运行您喜欢的任何操作,并使用它verify来检查它们对您的 mock 的影响PrintStream

于 2012-08-14T11:05:18.617 回答