这是我在某个服务类中的方法。它是公开的,因此应该对其进行测试。我根本不知道我应该测试什么。我会模拟 Writer
和 spyOn 函数调用,但使用此实现是不可能的(不是吗?)
我正在使用 Mockito
和 JUnit
目前,我只能创建抛出异常并断言该异常的函数
有什么帮助吗?
@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/