java - 如何测试这个文件写入,3lines 功能?

标签 java unit-testing testing mockito writer

这是我在某个服务类中的方法。它是公开的,因此应该对其进行测试。我根本不知道我应该测试什么。我会模拟 Writer 和 spyOn 函数调用,但使用此实现是不可能的(不是吗?)

我正在使用 MockitoJUnit

目前,我只能创建抛出异常并断言该异常的函数

有什么帮助吗?

@Override
public void initIndexFile(File emptyIndexFile) {
    try {
        Writer writer = new FileWriter(emptyIndexFile);
        writer.write("[]");
        writer.close();
    } catch (IOException e) {
        throw new IndexFileInitializationException(
            "Error initialization index file " + emptyIndexFile.getPath()
        );
    }
}

最佳答案

如果您认为添加特殊内容是业务逻辑,因此是您类的责任,那么创建 FileWriter 不是(根据 >单一职责模式

因此,您应该使用一个 FileWriterFactory,它被注入(inject)到您的被测类中。然后您可以模拟 FileWriterFactory 以返回 Writer 接口(interface)的模拟实现,然后您可以在该接口(interface)上检查它是否获得了预期的字符串。

你的 CuT 会变成这样:

private final WriterFactory writerFactory;

public ClassUnderTest(@Inject WriterFactory writerFactory){
   this.writerFactory = writerFactory;
}

@Override
public void initIndexFile(File emptyIndexFile) {
    try {
        Writer writer = writerFactory.create(emptyIndexFile);
        writer.write("[]");
        writer.close();
    } catch (IOException e) {
        throw new IndexFileInitializationException(
            "Error initialization index file " + emptyIndexFile.getPath()
        );
    }
}

和你对此的测试:

class Test{

  @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); 

  @Mock
  private FileWriterFactory fileWriterFactory;
  private Writer fileWriter = spy(new StringWriter());
  File anyValidFile = new File(".");
  @Test
  public void initIndexFile_validFile_addsEmptyraces(){
     //arrange
     doReturn(fileWriter).when(fileWriterFactory).create(any(File.class));

     // act
     new ClassUnderTest(fileWriterFactory).initIndexFile(anyValidFile);

     //assert
     verify(fileWriterFactory)create(anyValidFile);
     assertEquals("text written to File", "[]", fileWriter.toString());
     verify(fileWriter).close();
  }
}

此外,您可以轻松地检查您的 CuT 是否拦截了 IOException:

  @Rule
  public ExpectedException exception = ExpectedException.none();

  @Test
  public void initIndexFile_missingFile_IndexFileInitializationException(){
     //arrange
     doReturnThrow(new IOException("UnitTest")).when(fileWriterFactory).create(any(File.class));

     //assert
     exception.expect(IndexFileInitializationException.class);
     exception.expectMessage("Error initialization index file "+anyValidFile.getPath());

     // act
     new ClassUnderTest(fileWriterFactory).initIndexFile(anyValidFile);
  }

Nice! a factory just to test 3 lines of code! – Nicolas Filotto

这是一个很好的观点。

问题是:该类中是否有任何方法直接与 File 对象交互并且之后需要创建 FileWriter?

如果根据 KISS 原则答案是“否”(这很可能是这样),您应该直接注入(inject)一个 Writer 对象而不是工厂,并且您的方法不带 File 参数。

private final Writer writer;

public ClassUnderTest(@Inject Writer writer){
   this.writer = writer;
}

@Override
public void initIndexFile() {
    try {
        writer.write("[]");
        writer.close();
    } catch (IOException e) {
        throw new IndexFileInitializationException(
            "Error initialization index file " + emptyIndexFile.getPath()
        );
    }
}

修改后的测试:

class Test{       
  @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); 
  @Rule public ExpectedException exception = ExpectedException.none();

  @Mock
  private FileWriterFactory fileWriterFactory;
  @Mock
  private Writer failingFileWriter;
  private Writer validFileWriter = spy(new StringWriter());
  File anyValidFile = new File(".");
  @Test
  public void initIndexFile_validFile_addsEmptyraces(){
     //arrange         
     // act
     new ClassUnderTest(validFileWriter).initIndexFile();

     //assert
     verify(fileWriterFactory)create(anyValidFile);
     assertEquals("text written to File", "[]", fileWriter.toString());
     verify(fileWriter).close();
  }

  @Test
  public void initIndexFile_missingFile_IndexFileInitializationException(){
     //arrange
     doReturnThrow(new IOException("UnitTest")).when(failingFileWriter).write(anyString());

     //assert
     exception.expect(IndexFileInitializationException.class);
     exception.expectMessage("Error initialization index file "+anyValidFile.getPath());

     // act
     new ClassUnderTest(fileWriterFactory).initIndexFile(anyValidFile);
  }
}

关于java - 如何测试这个文件写入,3lines 功能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41808986/

相关文章:

python - 测试 SQLAlchemy 方言的正确方法是什么?

java - 如何在android中创建线性布局和中心按钮?

java - 在 eclipse 中设置 java 参数

WebPagetest 的 Java 测试客户端

java - 在 macOS 上使用 DTrace 分析 Java 应用程序

unit-testing - with-redefs 在 Windows 上的特定项目中不起作用

node.js - 我怎样才能让 mocha 单独运行我的测试?

ios - 如何在回归测试中模拟 UITouches?

java - 注入(inject) Autowiring 变量

testing - 什么是测试中的软件故障?