测试outputstream.write(<string>)而不创建文件</string>

时间:2012-02-17 12:26:42

标签: java testing tdd mockito

我正在测试java中的输出流,如下所示。

    Writer outputStream = getOutputStream(fileName);
    if(outputStream != null) {
        try {
            outputStream.write(inputText);
        }
        finally {
            outputStream.close();
        }
    }
    else {
        throw new IOException("Output stream is null");
    }

我正在编写一个模拟测试,如下所示

public void testFileWrite() throws IOException {
    when(testObj.getOutputStream(outputFileNameValidValue)).thenReturn(outputStreamMock);
    doNothing().when(outputStreamMock).write(Matchers.anyString());
    doNothing().when(bufferedReaderMock).close();

    testObj.write(outputFileNameValidValue, reveredFileInput);

    verify(outputStreamMock).write(Matchers.anyString());
    verify(outputStreamMock).close();
}

问题是当您创建OutputStreamWriter(new FileOutputStream(filename))磁盘上的物理文件时。

我们可以在没有实际在磁盘上写文件的情况下测试Outputstream.write吗?

由于 阿南德

5 个答案:

答案 0 :(得分:12)

您可以使用ByteArrayOutputStream将数据写入内存。您可以使用ByteArrayInputStream来读取它。

另一种方法是编写一个期望的OutputStream,它会在您尝试写入错误的字节时立即失败。这有助于确切了解测试失败的确切位置和原因。

答案 1 :(得分:2)

您可以尝试使用System.out作为输出,这实际上是一个Printstream,它是OutputStream的子类

请参阅: http://docs.oracle.com/javase/6/docs/api/java/lang/System.html http://docs.oracle.com/javase/6/docs/api/java/io/PrintStream.html

答案 2 :(得分:1)

正如其他建议你已经需要能够在你的测试类中注入一个模拟的OutputStream。由于您的测试类需要一个写入给定文件的OutputStream,您需要将一个可模拟的OutputStreamFactory注入到您正在测试的类中。

我有这个完全自包含的代码:

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import java.io.IOException;
import java.io.OutputStream;

import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class Test9328173 {

    private ClassUnderTest testObj;

    @Mock
    private OutputStreamFactory factory;

    @Mock
    private OutputStream stream;

    @Before
    public void setUp() throws Exception {
        testObj = new ClassUnderTest();
        testObj.factory = factory;
    }

    @Test
    public void testFileWrite() throws Exception {
        when(factory.create("filename")).thenReturn(stream);

        testObj.write("filename", new byte[]{1, 2, 3});

        verify(stream).write(new byte[]{1, 2, 3});
        verify(stream).close();
    }

    private class ClassUnderTest {

        private OutputStreamFactory factory;

        public void write(String filename, byte[] content) throws IOException {
            OutputStream stream = factory.create(filename);
            try {
                stream.write(content);
            } finally {
                stream.close();
            }
        }
    }

    private interface OutputStreamFactory {

        OutputStream create(String filename);
    }
}

答案 3 :(得分:0)

你应该模拟你的getOutputStream:应该返回模拟的输出流对象。调用new FileOutputStream确实会在磁盘上创建文件。

从理论上讲,你可以模拟文件系统本身,但它要复杂得多。

BTW if(outputStream != null)是多余的:流永远不能为空。如果无法创建,则该方法应抛出异常。它不是C,它是Java。 :)

答案 4 :(得分:0)

您应该让模拟的getOutputStream(String)返回java.io.StringWriter,然后您可以声明已写入预期内容。

public void testFileWrite() throws IOException {
    StringWriter writer = new StringWriter();
    when(testObj.getOutputStream(outputFileNameValidValue)).thenReturn(writer);

    testObj.write(outputFileNameValidValue, reveredFileInput);

    assertEquals(reveredFileInput, writer.toString());

    verify(writer).close();
}