【发布时间】:2010-09-12 20:14:51
【问题描述】:
我正在编写一个组件,给定一个 ZIP 文件,它需要:
- 解压文件。
- 在解压后的文件中查找特定的 dll。
- 通过反射加载该 dll 并在其上调用方法。
我想对这个组件进行单元测试。
我很想编写直接处理文件系统的代码:
void DoIt()
{
Zip.Unzip(theZipFile, "C:\\foo\\Unzipped");
System.IO.File myDll = File.Open("C:\\foo\\Unzipped\\SuperSecret.bar");
myDll.InvokeSomeSpecialMethod();
}
但人们经常说,“不要编写依赖文件系统、数据库、网络等的单元测试。”
如果我以一种对单元测试友好的方式编写它,我想它应该是这样的:
void DoIt(IZipper zipper, IFileSystem fileSystem, IDllRunner runner)
{
string path = zipper.Unzip(theZipFile);
IFakeFile file = fileSystem.Open(path);
runner.Run(file);
}
耶!现在它可以测试了;我可以将测试替身(模拟)输入 DoIt 方法。但代价是什么?我现在必须定义 3 个新接口才能使其可测试。我到底在测试什么?我正在测试我的 DoIt 函数是否与其依赖项正确交互。它不会测试 zip 文件是否正确解压缩等。
感觉我不再是在测试功能了。感觉就像我只是在测试班级互动。
我的问题是这样的:对依赖于文件系统的东西进行单元测试的正确方法是什么?
edit我使用的是 .NET,但这个概念也可以应用 Java 或本机代码。
【问题讨论】:
-
人们说不要在单元测试中写入文件系统,因为如果您想写入文件系统,那么您不了解单元测试的构成。单元测试通常与单个 real 对象(被测单元)交互,并且所有其他依赖项都被模拟并传入。然后,测试类由测试方法组成,这些方法通过对象的逻辑路径验证方法和仅被测单元中的逻辑路径。
-
在您的情况下,唯一需要单元测试的部分是
myDll.InvokeSomeSpecialMethod();,您可以在其中检查它在成功和失败情况下是否都能正常工作,所以我不会对DoIt进行单元测试,但@987654325 @ 说滥用单元测试来仔细检查整个过程是否有效是可以接受的滥用,因为这将是伪装单元测试的集成测试,因此不需要严格应用正常的单元测试规则
标签: unit-testing dependency-injection dependencies