如何在JUnit中测试IO代码?

acc*_*c15 3 java junit mocking junit4 mockito

我想测试两个服务:

  1. 构建文件名的服务
  2. 将一些数据写入第一服务提供的文件的服务

首先,我正在构建一些复杂的文件结构(仅举例{user}/{date}/{time}/{generatedId}.bin)

第二,我将数据写入第一服务传递的文件(第一服务调用第二服务)

如何使用模拟测试这两种服务而不进行任何真正的IO交互?

仅举例如:

第一服务:

public class DefaultLogService implements LogService
{

    public void log(SomeComplexData data)
    {
        serializer.write(new FileOutputStream(buildComplexFileStructure()), data);
        or
        serializer.write(buildComplexFileStructure(), data);
        or
        serializer.write(new GenericInputEntity(buildComplexFileStructure()), data);
    }

    private ComplextDataSerializer serializer; // mocked in tests
}
Run Code Online (Sandbox Code Playgroud)

第二服务:

public class DefaultComplexDataSerializer implements ComplexDataSerializer
{

    void write(InputStream stream, SomeComplexData data) {...}
    or
    void write(File file, SomeCompexData data) {...}
    or
    void write(GenericInputEntity entity, SomeComplexData data) {...}

}
Run Code Online (Sandbox Code Playgroud)

在第一种情况下,我需要传递FileOutputStream,这将创建一个文件(即我无法测试第一个服务)

在第二种情况下,我需要传递文件.如果我需要测试将写入指定文件的数据,我在第二次服务测试中该怎么办?(我无法测试第二次服务)

在第三种情况下,我认为我需要一些通用IO对象,它将包装文件.也许为此目的有一些现成的解决方案?

Kay*_* II 5

在第一种情况下,如果您正在测试文件名生成,为什么还要关心文件本身?您不想测试FileOutputStream.

我假设你的方法看起来像这样:

public File buildComplexFileStructure() {
    // code
}
Run Code Online (Sandbox Code Playgroud)

您的测试看起来像这样:

@Test public void test() throws Exception {
    File expected = <what you expect to be generated>;
    File actual = new DefaultLogService().buildComplexFileStructure();
    assertEquals(expected, actual);
}
Run Code Online (Sandbox Code Playgroud)

如果该方法未公开公开,则只需将其公开给测试(默认或受保护).

在第二种情况下,您是否无法将测试测试中的ByteArrayOutputStream传递给您的方法,然后验证写入的内容是什么?即:

@Test public void test() throws Exception {
    btye[] expected = <expected data>;
    ByteArrayOutputStream actualStream = new ByteArrayOutputStream();
    new DefaultComplexDataSerializer().write(actualStream, data);
    byte[] actualData = actualStream.toByteArray();
    // compare expected and actualData
}
Run Code Online (Sandbox Code Playgroud)

  • @acc15 瞄准 100% 覆盖率实际上是一件坏事......不要进入度量游戏:) 你必须测试重要的东西,而不是每个类。我的两分钱:) (2认同)