java - 模拟 OutputStream#flush 方法

标签 java unit-testing mockito java-io

我有:我有服务类的方法void方法。此方法从远程获取一些数据,然后使用 OutputStream 刷新它们。

public void pullAndFlushData(URI uri, Params params) {
  InputStream input = doHttpRequest(uri, params);
  OutputStream output = new OutputStream("somepath");
  IOUtils.copyLarge(input, output);
  output.flush();
  output.close();
}

我想要:测试此方法的结果。所以我想模拟 output.flush() 并检查它是否包含正确的数据。

问题:如何模拟OutputStream#flush方法

最佳答案

您当前的代码将无法工作:

 OutputStream output = new OutputStream("SomePath");

...无法编译,因为 OutputStream 是抽象的。

因此,您需要在某个地方告诉该方法要使用什么 OutputStream。为了使其更具可测试性,请将流作为参数。

 public void pullAndFlushData(OutputStream output, URI uri, Params params) {
    InputStream input = doHttpRequest(uri, params);
    IOUtils.copyLarge(input, output);
    output.flush();
    output.close();
 }

或者,output 可以是对象中的一个字段,由构造函数或 setter 填充。或者您可以将对象传递给工厂。无论您选择其中哪一个,都意味着调用者可以控制使用哪种类型的 OutputStream——对于生产代码,使用 FileOutputStream;对于测试,一个ByteArrayOutputStream

您可能希望在此处查看 close() OutputStream 的决定 - 而是在打开 OutputStream 的同一 block 中执行此操作。

现在您可以通过让单元测试提供 OutputStream 来测试它。

@Test
public void testPullAndFlushData() {
     URI uri = ...;
     Params params = ...;
     ByteArrayOutputStream baos = new ByteArrayOutputStream();
     someObject.pullAndFlushData(baos, uri, params);
     assertSomething(..., baos.toByteArray());
}

这不使用 Mockito,但对于测试使用 OutputStream 的方法来说,这是一个很好的模式。

您可以让 Mockito 模拟 OutputStream 并以相同的方式使用它 - 设置对它的 write() 调用的期望。但是,copyLarge() 分块数据的方式会变得非常脆弱。

您还可以使用 Mockito 的 spy() 来检查是否对真实的 ByteArrayOutputStream 进行了调用。

@Test
public void testPullAndFlushData() {
     URI uri = ...;
     Params params = ...;
     ByteArrayOutputStream spybaos = spy(new ByteArrayOutputStream());
     someObject.pullAndFlushData(spybaos, uri, params);
     assertSomething(..., spybaos.toByteArray());
     verify(spybaos).flush(); // asserts that flush() has been called.
}

但是,请注意,Mockito 团队非常不愿意提供 spy(),并且在大多数情况下不认为这是一种很好的测试方法。阅读Mockito docs由于原因。

关于java - 模拟 OutputStream#flush 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24260498/

相关文章:

java - 通过 Java 的 SSL 套接字连接

c# - 模拟 OpenXML SDK SpreadsheetDocument

java - java中测试数据库类

c# - 使用最小起订量测试 Controller

ios - Xcode 10 并行测试套件测试速度较慢且测试数量较少

java - 捕获参数传递给 powermockito 中的 stub

java - Mockito:如何替换被测类调用的类的方法?

java - 如何为正在调用其他私有(private)方法的私有(private) void 方法编写单元测试?

java - 想要在 JTable 中的每条记录后插入空行

java - 创建 "view"的 Java 列表