Java 如何在JUnit中测试IO代码?

Java 如何在JUnit中测试IO代码?,java,junit,mocking,junit4,mockito,Java,Junit,Mocking,Junit4,Mockito,我想测试两个服务: 生成文件名的服务 将一些数据写入第一个服务提供的文件的服务 首先,我构建了一些复杂的文件结构(例如{user}/{date}/{time}/{generatedId}.bin) 第二步,我将数据写入第一个服务传递的文件(第一个服务调用第二个服务) 如何使用mock测试这两个服务,而不进行任何实际操作 举个例子: 第一次服务: public class DefaultLogService implements LogService { public void log(

我想测试两个服务:

  • 生成文件名的服务
  • 将一些数据写入第一个服务提供的文件的服务
  • 首先,我构建了一些复杂的文件结构(例如
    {user}/{date}/{time}/{generatedId}.bin

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

    如何使用mock测试这两个服务,而不进行任何实际操作

    举个例子:

    第一次服务:

    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
    }
    
    第二项服务:

    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) {...}
    
    }
    
    在第一种情况下,我需要传递FileOutputStream,它将创建一个文件(即,我无法测试第一个服务)

    在第二种情况下,我需要传递文件。如果我需要测试将写入指定文件的数据,在第二次服务测试中我可以做什么?(我无法测试第二个服务)

    在第三种情况下,我想我需要一些通用IO对象来包装文件。
    也许有一些现成的解决方案可用于此目的?

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

    我假设您的方法如下所示:

    public File buildComplexFileStructure() {
        // code
    }
    
    @Test public void test() throws Exception {
        File expected = <what you expect to be generated>;
        File actual = new DefaultLogService().buildComplexFileStructure();
        assertEquals(expected, actual);
    }
    
    您的测试将如下所示:

    public File buildComplexFileStructure() {
        // code
    }
    
    @Test public void test() throws Exception {
        File expected = <what you expect to be generated>;
        File actual = new DefaultLogService().buildComplexFileStructure();
        assertEquals(expected, actual);
    }
    
    @Test public void Test()引发异常{
    应为文件=;
    File actual=new DefaultLogService().buildComplexFileStructure();
    资产质量(预期、实际);
    }
    
    如果该方法没有公开,那么只需将其公开给测试(默认或受保护)

    在第二种情况下,您能否将测试中的ByteArrayOutputStream传递到方法中,然后验证写入它的内容?i、 e:

    @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
    }
    
    @Test public void Test()引发异常{
    b预期为[]字节=;
    ByteArrayOutputStream实际流=新建ByteArrayOutputStream();
    新建DefaultComplexDataSerializer().write(实际流,数据);
    字节[]actualData=actualStream.toByteArray();
    //比较预期数据和实际数据
    }
    
    在这种情况下,我将失去我的100%测试覆盖率统计=(@acc15瞄准100%覆盖率实际上是一件坏事…不要进入度量游戏:)你必须测试重要的内容,而不是每个类。我的两分钱:)可能是