您的问题暴露了刚刚进入它的开发人员测试中最困难的部分之一:
“我到底要测试什么?”
您的示例不是很有趣,因为它只是将一些 API 调用粘合在一起,因此如果您要为其编写单元测试,您最终只会断言调用了该方法。像这样的测试将您的实现细节与测试紧密结合在一起。这很糟糕,因为现在每次更改方法的实现细节时都必须更改测试,因为更改实现细节会破坏您的测试!
进行糟糕的测试实际上比根本没有测试更糟糕。
在您的示例中:
void DoIt(IZipper zipper, IFileSystem fileSystem, IDllRunner runner)
{
string path = zipper.Unzip(theZipFile);
IFakeFile file = fileSystem.Open(path);
runner.Run(file);
}
虽然您可以传入模拟,但测试方法中没有逻辑。如果您要为此尝试进行单元测试,它可能看起来像这样:
// Assuming that zipper, fileSystem, and runner are mocks
void testDoIt()
{
// mock behavior of the mock objects
when(zipper.Unzip(any(File.class)).thenReturn("some path");
when(fileSystem.Open("some path")).thenReturn(mock(IFakeFile.class));
// run the test
someObject.DoIt(zipper, fileSystem, runner);
// verify things were called
verify(zipper).Unzip(any(File.class));
verify(fileSystem).Open("some path"));
verify(runner).Run(file);
}
恭喜,您基本上将DoIt()
方法的实现细节复制粘贴到测试中。快乐维护。
当您编写测试时,您想测试WHAT而不是HOW。
有关更多信息,请参阅黑盒测试。
WHAT是您的方法的名称(或者至少应该是)。HOW是你方法中的所有小实现细节。好的测试可以让你在不破坏WHAT的情况下更换HOW。
这样想,问问自己:
“如果我更改此方法的实施细节(不更改公共合同)会破坏我的测试吗?”
如果答案是肯定的,那么您正在测试HOW而不是WHAT。
为了回答您关于使用文件系统依赖项测试代码的具体问题,假设您对文件进行了一些更有趣的事情,并且您想将 a 的 Base64 编码内容保存byte[]
到文件中。您可以为此使用流来测试您的代码是否正确,而无需检查它是如何执行的。一个例子可能是这样的(在 Java 中):
interface StreamFactory {
OutputStream outStream();
InputStream inStream();
}
class Base64FileWriter {
public void write(byte[] contents, StreamFactory streamFactory) {
OutputStream outputStream = streamFactory.outStream();
outputStream.write(Base64.encodeBase64(contents));
}
}
@Test
public void save_shouldBase64EncodeContents() {
OutputStream outputStream = new ByteArrayOutputStream();
StreamFactory streamFactory = mock(StreamFactory.class);
when(streamFactory.outStream()).thenReturn(outputStream);
// Run the method under test
Base64FileWriter fileWriter = new Base64FileWriter();
fileWriter.write("Man".getBytes(), streamFactory);
// Assert we saved the base64 encoded contents
assertThat(outputStream.toString()).isEqualTo("TWFu");
}
测试使用 a但在应用程序中(使用依赖注入),真正的ByteArrayOutputStream
StreamFactory(可能称为 FileStreamFactory)FileOutputStream
将从.outputStream()
File
这里方法的有趣之write
处在于它以 Base64 编码的形式写入内容,这就是我们测试的内容。对于您的DoIt()
方法,这将更适合使用集成测试进行测试。