Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/365.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 模拟输出流#刷新方法_Java_Unit Testing_Mockito_Java Io - Fatal编程技术网

Java 模拟输出流#刷新方法

Java 模拟输出流#刷新方法,java,unit-testing,mockito,java-io,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); o

我有:我有服务类的方法
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

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();
}
您可能希望在此处查看关闭输出流的决定,而不是在打开输出流的同一块中执行

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

@Test
public void testPullAndFlushData() {
     URI uri = ...;
     Params params = ...;
     ByteArrayOutputStream baos = new ByteArrayOutputStream();
     someObject.pullAndFlushData(baos, uri, params);
     assertSomething(..., baos.toByteArray());
}
@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,但它是测试使用OutputStream的方法的一个好模式

@Test
public void testPullAndFlushData() {
     URI uri = ...;
     Params params = ...;
     ByteArrayOutputStream baos = new ByteArrayOutputStream();
     someObject.pullAndFlushData(baos, uri, params);
     assertSomething(..., baos.toByteArray());
}
@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模拟输出流,并以相同的方式使用它——为调用它的
write()
调用设置期望值。但是
copyragle()
对数据进行分块的方式会变得非常脆弱

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

@Test
public void testPullAndFlushData() {
     URI uri = ...;
     Params params = ...;
     ByteArrayOutputStream baos = new ByteArrayOutputStream();
     someObject.pullAndFlushData(baos, uri, params);
     assertSomething(..., baos.toByteArray());
}
@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()
,而且在大多数情况下,他们认为这不是一种好的测试方法。阅读以了解原因。

如果您接受一个
OutputStream
作为方法的参数,您可以通过通过通过tearrayoutputstream传递一个
并测试内容来测试该方法。我看不到用当前代码进行模拟的机会。注意:您的方法没有做任何有用的事情。我想这是因为你简化了这个问题。我认为你过于简化了它,这将使我们更难建议如何测试它。@Duncan我不接受
OutputSteam
作为我方法的参数
IOUtils
是第三方谷歌class@Duncan它从某些服务获取数据,并将其保存到文件中。是的,它可以修改两个操作的数据。但在这种情况下,这真的无关紧要。我建议你应该添加一个论点。有时,您的代码需要更改以使其能够进行测试。+1这正是我所想的。(虽然我很懒,写了一条评论,但这不是一个好的答案)。我几乎会考虑删除你最后几段——我们不希望新用户认为这是一个很好的测试方法。邓肯说,他确实想检查FrHuSE()。我要说的是Mockito团队不同意。