无法使用JUnit和Mockito测试反序列化类

时间:2019-01-14 15:11:57

标签: java unit-testing mockito junit4

目的:使用TDD(我最近了解到现在对此感到遗憾)构建一个stickynote应用程序

问题:我希望所有“注释”将由自己的单独类进行序列化和反序列化。我希望使用TDD方法,但是我什至无法测试NoteReader类(反序列化器)的快乐路径,更不用说特殊情况了。

以下是代码:

package com.domainname.applicationname;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.List;

public class NoteReader {
    private final FileInputStream fileInputStream;

    public NoteReader(FileInputStream fileInputStream) {
        this.fileInputStream = fileInputStream;
    }

    @SuppressWarnings("unchecked")
    public List<Note> load() {
        ObjectInputStream objectInputStream = null;
        List<Note> output = null;
        try {
            objectInputStream = new ObjectInputStream(fileInputStream);
            output = (List<Note>) objectInputStream.readObject();
            objectInputStream.close();
        } catch (ClassNotFoundException | IOException e) {
            e.printStackTrace();
        }
        return output;
    }
}

这是单元测试代码:

package com.domainname.applicationname;

import org.junit.*;
import org.mockito.Mockito;

import java.io.*;
import java.util.Arrays;
import java.util.List;

public class NoteReaderTest {
    private FileInputStream dummyFileInputStream;
    private NoteReader noteReaderDummy;

    private List<Note> expectedOutput = Arrays.asList(
            new Note("some written text"),
            new Note("some other written text", NoteColor.lightGreen)
    );

    private ByteArrayOutputStream byteArrayOutputStream;
    private ObjectOutputStream objectOutputStream;
    private byte[] bytesToBeDeserialized;

    @Before
    public void setUp() throws IOException {
        dummyFileInputStream = Mockito.mock(FileInputStream.class);
        noteReaderDummy = new NoteReader(dummyFileInputStream);

        byteArrayOutputStream = new ByteArrayOutputStream();
        objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
    }

    @After
    public void tearDown() throws IOException {
        noteReaderDummy = null;
        byteArrayOutputStream.flush();
        objectOutputStream.flush();
        objectOutputStream.close();
    }

    @Test
    public void shouldLoadTheListOfNotes() throws IOException {
        //given
        objectOutputStream.writeObject(expectedOutput);
        bytesToBeDeserialized = byteArrayOutputStream.toByteArray();
        int intValueOfByteArray = dummyFileInputStream.read(bytesToBeDeserialized);
        //when
        Mockito.when(
                dummyFileInputStream.read()
        ).thenReturn(
                intValueOfByteArray
        );

        //then
        Assert.assertEquals(
                "the notes have not been loaded",
                expectedOutput,
                noteReaderDummy.load()
        );
    }
}

这使我陷入无限循环,这让我发疯。

问题:如何测试反序列化类?上面的代码我在做什么错了?

2 个答案:

答案 0 :(得分:0)

我会在您的应用中添加一个文件,然后将其加载以进行测试。

@Test
public void givenUsingPlainJava_whenConvertingFileToInputStream_thenCorrect() 
  throws IOException {
    File initialFile = new File("src/main/resources/sample.txt");
    InputStream targetStream = new FileInputStream(initialFile);
}

enter image description here

答案 1 :(得分:0)

对于可能面临相同问题的其他任何人,请重写Note类的hashCode()和equals()方法,使其按我预期的方式工作。将列表实例化为ArrayList或LinkedList。这为我解决了。我不知道的一件事是如何与它一起使用Mockito。因此,我接受了@PhilNinan的建议,并将TemporaryFolder与tempFile一起使用。然后序列化到该文件并读取该文件(不理想,但找不到其他方法)。 NoteReader:

package com.somedomainname.someapplication;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.List;

class NoteReader {
    private final FileInputStream fileInputStream;

    NoteReader(FileInputStream fileInputStream) {
        this.fileInputStream = fileInputStream;
    }

    @SuppressWarnings("unchecked")
    List<Note> load() throws IOException {
        ObjectInputStream objectInputStream = null;
        List<Note> output = new ArrayList<>();

        try {
            objectInputStream = new ObjectInputStream(fileInputStream);
            while (fileInputStream.available() != 0) {
                Note n = (Note) objectInputStream.readObject();
                output.add(n);
            }

        } catch (ClassNotFoundException | IOException e) {
            fileInputStream.close();
            assert objectInputStream != null;
            objectInputStream.close();

            e.printStackTrace();
        }
        return output;
    }

}

NoteReaderTest类:

package com.somedomainname.someapplicationname;

import org.junit.*;
import org.junit.rules.TemporaryFolder;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class NoteReaderTest {
    private NoteReader noteReaderDummy;

    private ObjectOutputStream objectOutputStream;

    @Rule
    public TemporaryFolder temporaryFolder = new TemporaryFolder();

    private File tempFile;

    private static List<Note> inputList = new ArrayList<>();
    static {
        inputList.add(new Note("some written text"));
        inputList.add(new Note("some other written text", NoteColor.lightGreen));
    }

    private static List<Note> anotherList = new ArrayList<>();
    static {
        anotherList.add(new Note("qazwsxedcrfv"));
        anotherList.add(new Note("qwertyuiopasdfghjkl", NoteColor.lightRed));
    }

    @Before
    public void setUp() throws IOException {
        tempFile = temporaryFolder.newFile("someBullshit.ser");
        objectOutputStream = new ObjectOutputStream(new FileOutputStream(tempFile));

        for(Note n : inputList) {
            objectOutputStream.writeObject(n);
        }

        noteReaderDummy = new NoteReader(new FileInputStream(tempFile));

    }

    @After
    public void tearDown() throws IOException {
        objectOutputStream.flush();
        objectOutputStream.close();
        tempFile = null;
        temporaryFolder = null;
        noteReaderDummy = null;

    }

    /**
     * This test method tests the happy path of the NoteReader.load() method.
     * @throws IOException
     */

    @Test
    public void shouldLoadTheListOfNotes() throws IOException {
        //given

        //then
        List<Note> output = noteReaderDummy.load();
        Assert.assertEquals(
                "the notes have not been loaded",
                inputList,
                output
        );

    }

    /**
     * This test method is responsible for confirming that the output of the
     * NoteReader.load() method doesn't stray from the expected one.
     * @throws IOException
     */

    @Test
    public void shouldNotLoadTheOtherListOfNotes() throws IOException {
        //given

        //then
        List<Note> output = noteReaderDummy.load();
        Assert.assertNotEquals(
                "it loaded the wrong fucking list",
                anotherList,
                output
        );

    }

    /**
     * this test method is responsible for checking that the output of
     * the method NoteReader.load() is not null
     * @throws IOException
     */

    @Test
    public void shouldNotBeNull() throws IOException {
        //given

        //then
        List<Note> output = noteReaderDummy.load();
        Assert.assertNotNull(
                "fuck it's null",
                output
        );
    }
}