你如何模拟输出流?

Tom*_*son 15 java outputstream mocking stream

'输出蒸汽'是指任何接收字节序列或字符或其他内容的对象.所以,java.io.OutputStream,还有java.io.Writer,javax.xml.stream.XMLStreamWriter的writeCharacters方法等等.

我正在为一个类编写基于模拟的测试,该类的主要功能是将数据流写入其中一个(XMLStreamWriter,就像它一样).

问题是数据流是在对write方法的一系列调用中编写的,但重要的不是调用,而是数据.例如,给定XMLStreamWriter out,这些:

out.writeCharacters("Hello, ");
out.writeCharacters("world!");
Run Code Online (Sandbox Code Playgroud)

相当于:

out.writeCharacters("Hello, world!");
Run Code Online (Sandbox Code Playgroud)

这对我的目的来说无关紧要.将会有一些特定的调用序列,但我不在乎它是什么,因此我不想写出对该特定序列的期望.我只是希望能够以任何方式写入某个特定的数据流.

一种选择是切换到基于状态的测试.我可以在缓冲区中累积数据,并对其进行断言.但是因为我正在编写XML,这意味着要做一些相当复杂和丑陋的断言.模拟似乎是处理编写XML的更大问题的更好方法.

那么我如何用模拟做到这一点?

我正在使用Moxie进行模拟,但我很想知道任何模拟库的方法.

Mr.*_*art 17

测试输出或输入流的一种相当优雅的策略是使用PipedInputStreamPipedOutputStream类.您可以在测试设置中将它们连接在一起,然后检查执行目标方法后写入的内容.

您可以在另一个方向上准备一些输入,然后让测试从输入流中读取这些准备好的数据.

在您的情况下,您可以使用PipedOutputStream 模拟该"out"变量,并以这种方式将PipedInputStream插入其中:

private BufferedReader reader;

@Before
public void init() throws IOException {
    PipedInputStream pipeInput = new PipedInputStream();
    reader = new BufferedReader(
            new InputStreamReader(pipeInput));
    BufferedOutputStream out = new BufferedOutputStream(
            new PipedOutputStream(pipeInput))));
    //Here you will have to mock the output somehow inside your 
    //target object.
    targetObject.setOutputStream (out);
    }


@Test
public test() {
    //Invoke the target method
    targetObject.targetMethod();

    //Check that the correct data has been written correctly in 
    //the output stream reading it from the plugged input stream
    Assert.assertEquals("something you expects", reader.readLine());
    }
Run Code Online (Sandbox Code Playgroud)


Cha*_*lie 7

我承认我可能偏向使用ByteArrayOutputStream作为最低级别的 OutputStream,在执行后获取数据并执行所需的任何断言。(也许使用 SAX 或其他 XML 解析器读取数据并深入研究结构)

如果你想用模拟来做到这一点,我承认我有点偏向Mockito ,并且我认为你可以使用自定义答案来完成你想要做的事情,当用户在你的模拟上调用 writeCharacters 时,将只需将它们的参数附加到 Buffer 中,然后您就可以对其进行断言。

这是我脑子里的想法(手写的,尚未执行,因此语法问题是可以预料的:))

public void myTest() {
    final XMLStreamWriter mockWriter = Mockito.mock(XMLStreamWriter.class);
    final StringBuffer buffer = new StringBuffer();
    Mockito.when(mockWriter.writeCharacters(Matchers.anyString())).thenAnswer(
        new Answer<Void>() {
            Void answer(InvocationOnMock invocation) {
                buffer.append((String)invocation.getArguments()[0]);
                return null;
            }
        });
    //... Inject the mock and do your test ...
    Assert.assertEquals("Hello, world!",buffer.toString());
}    
Run Code Online (Sandbox Code Playgroud)