在我的程序中,我使用SevenZipSharp生成zip文件。SevenZipSharp是一个托管DLL,它加载另一个DLL, 7z.dll。我使用SevenZipCompressor.SetLibraryPath手动将SevenZipSharp的路径设置为7z.dll。
当我在调试模式下执行我的程序时,这一切都很好,它生成的zip文件如您所愿。然而,当我用mstest执行单元测试时,SevenZipSharp总是给我以下错误:
测试方法抛出异常:SevenZip。不能加载7-zip库或内部COM错误!消息:failed to load library.
我怀疑MSTest可能正在做一些阻止SevenZipSharp加载7z.dll的事情,比如在安全严密的沙箱(或其他东西)中运行。我是c#和MSTest的新手…)
有人知道可能会发生什么吗?
谢谢!
尽管问题假设了一个可疑的场景,但MSTest不加载所需dll的一般问题似乎是一个常见的问题,值得不那么轻蔑的回答。
-
默认情况下,MSTest将把它认为测试容器需要的程序集复制到默认结果文件夹的Out文件夹中,该文件夹在每次运行时都会更改。
-
MSTest并不总是自动正确地推断必要的程序集;如果没有对程序集的显式直接引用,则不会复制该程序集。此外,本机dll通常不会被检测到。
-
我不知道有直接选项来设置MSTest搜索路径。你可以按照上面的建议使用procmon.exe来确定搜索路径(它基本上是标准的Windows DLL搜索)。
-
默认搜索路径不包括启动目录,我认为这是造成混乱的原因。当测试运行时,当前目录是测试结果"Out"目录,而不是MSTest启动目录。
通过这种方式,您可以准确地控制哪些dll被复制到您的测试目录。请参阅创建测试设置以从Visual Studio运行自动测试以获取有关此操作的详细信息。
当然,DLL加载失败可能是由于缺少依赖,并且错误消息中提到的DLL可能本身存在。您可以使用依赖项查看器或procmon来获取dll中的意外依赖项。
Visual Studio 2017(可能还有2015)提供了两种新的方法来指示您的测试需要本机dll或其他文件,而不需要测试设置文件:
1:添加一个链接到您的测试项目的dll,并告诉VS将其复制到输出目录。在解决方案资源管理器中右键单击该项目,然后选择"添加>现有项目"。浏览到7z.dll,单击Add按钮旁边的向下箭头,然后选择Add as Link。然后在解决方案资源管理器中选择新的7z.dll项目,按alt-Enter调出属性,将"复制到输出目录"设置为"更新时复制"(或"始终复制")。
2:将DeploymentItemAttribute
附加到您的测试类。此属性的构造函数接受单个字符串参数,该参数是要在类中对测试可用的文件的路径。它相对于测试项目的输出目录。
考虑使用优秀的SysInternals工具中的Process Monitor (aka procmon.exe)
来监视您的测试工具(MSTest)。它将显示可执行文件在哪里查找7z.dll
您确定希望单元测试涉及外部库吗?理想情况下,你应该有机制来代替外部的东西,例如mock对象,因为测试外部库,这样实际上把你的测试变成了一个集成测试。
对于像SevenZipSharp这样的流行库,你可以假设它经过了适当的测试,并且你可以手工集成测试来验证它在你的程序中正确地执行。
我会考虑通过依赖注入、模拟框架等来摆脱依赖,让你的单元测试只测试你自己的代码。
研究工厂方法或抽象工厂设计模式,了解如何轻松替换此类依赖。
一个好的开始是创建您自己的ICustomZipInterface,并使用包装器模式封装生产代码的zip逻辑。在单元测试中,将包装器类替换为虚拟实现。例如,虚拟实现可能会记录您如何访问zip组件,您可以使用该信息来验证代码,而不是检查是否实际创建了zip文件。