简体   繁体   中英

Testing outputstream.write(<String>) without creating a file

I am testing a output stream in java something like below.

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

I am write a mockito test as below

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();
}

The problem is when you create OutputStreamWriter(new FileOutputStream(filename)) a physical file on the disk is created.

Can we test Outputstream.write without actually writing a file on the disk?

Thanks Anand

You can use ByteArrayOutputStream which writes the data in memory. You can read this with a ByteArrayInputStream.

An alternative is to write an expecting OutputStream which fails as soon as you attempt to write an incorrect byte. This can be helpful to see exactly where/why a test fails.

You could try using System.out for your output which is actually a Printstream, which is a subclass of OutputStream

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

As other suggested already you need to be able to inject a mocked OutputStream in your class under test. As your class under test needs a OutputStream which writes into a given file, you will need to inject a mockable OutputStreamFactory into your class under test.

I have this code for you which is fully self contained:

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);
    }
}

You should mock up your getOutputStream : is should return mocked output stream object. Invocation of new FileOutputStream indeed creates file on disk.

Theoretically you can mock up file system itself but it is much more complicated.

And BTW if(outputStream != null) is redundant: stream can never be null. If it cannot be created the method should throw exception. It is not C, it is Java. :)

You should have the mocked getOutputStream(String) return a java.io.StringWriter and you can then assert that the expected content was written.

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();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM