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

Unable to test a deserialization class using JUnit and Mockito

目的:使用 TDD 构建一个便利贴应用程序(这是我最近学到的,现在很后悔)

问题:我希望所有 "Note" 都由他们自己的 class 序列化和反序列化。我希望使用 TDD 方法,但我什至无法测试 NoteReader class(反序列化器)的快乐路径,更不用说极端情况了。

代码如下:

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

这有一个 b/me 无限循环,快把我逼疯了。

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

我会向您的应用程序添加一个文件,然后加载该文件以进行测试。

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

https://www.baeldung.com/convert-file-to-input-stream

对于可能面临相同问题的任何其他人,请重写注释 class 的 hashCode() 和 equals() 方法,使其按照我的预期工作。将 List 实例化为 ArrayList 或 LinkedList。这为我解决了。我无法弄清楚的一件事是如何将 Mockito 与它一起使用。所以我接受了@PhilNinan 的建议并使用带有 tempFile 的 TemporaryFolder。然后序列化到该文件并读取该文件(不理想但找不到其他方法)。 笔记阅读器:

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 class:

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