C# Can';t在使用MS Test执行测试时加载DLL

C# Can';t在使用MS Test执行测试时加载DLL,c#,mstest,sevenzipsharp,C#,Mstest,Sevenzipsharp,在我的程序中,我使用SevenZipSharp生成zip文件。SevenZipSharp是一个托管DLL,它加载另一个DLL 7z.DLL。我正在使用SevenZipCompressor.SetLibraryPath手动将SevenZipSharp的路径设置为7z.dll 当我在调试模式下执行我的程序时,这一切都很好,它生成的zip文件非常好。但是,当我使用mstest执行单元测试时,SevenZipSharp总是给我以下错误: 测试方法引发异常: SevenZip.SevenzipLibrar

在我的程序中,我使用SevenZipSharp生成zip文件。SevenZipSharp是一个托管DLL,它加载另一个DLL 7z.DLL。我正在使用SevenZipCompressor.SetLibraryPath手动将SevenZipSharp的路径设置为7z.dll

当我在调试模式下执行我的程序时,这一切都很好,它生成的zip文件非常好。但是,当我使用mstest执行单元测试时,SevenZipSharp总是给我以下错误:

测试方法引发异常: SevenZip.SevenzipLibrary异常:无法加载7-zip库或 内部COM错误!消息:未能加载库

我怀疑MSTest可能正在做一些阻止SevenZipSharp加载7z.dll的事情,比如在安全严密的沙箱中运行(或者其他什么。我是C#和MSTest的新手……)

有人知道会发生什么吗


谢谢大家!

考虑使用来自卓越的
进程监视器(aka procmon.exe)
来监视您的测试线束(MSTest)。它将显示可执行文件查找7z.dll的位置。

您确定要让单元测试包含外部库吗?理想情况下,您应该具有用模拟对象等替换外部内容的机制,因为这样测试外部库实际上会将您的测试转化为集成测试

对于像SevenZipSharp这样的流行库,您可以假设它经过了正确的测试,并且可以进行手动集成测试来验证它在您的程序中是否正确执行

我会考虑通过依赖注入、模拟框架等来消除依赖性,并让您的单元测试只测试自己的代码。

研究工厂方法或抽象工厂设计模式,了解如何轻松替换此类依赖关系的技巧


一个好的开始是创建您自己的ICustomZipInterface,并使用包装器模式封装生产代码的zip逻辑。在单元测试中,用虚拟实现替换该包装器类。例如,虚拟实现可能会记录您如何访问zip组件,并且您可以使用该信息来验证代码,而不是检查是否实际创建了zip文件

尽管这个问题假设了一个有问题的场景,但MSTest没有加载所需DLL的一般问题似乎是一个常见的问题,应该得到一个不那么轻蔑的答案

  • 默认情况下,MSTest会将它认为测试容器需要的程序集复制到默认结果文件夹的Out文件夹中,该文件夹在每次运行时都会更改

  • MSTest并不总是自动正确推断必要的组件;如果没有对程序集的显式直接引用,则不会复制该程序集。此外,通常不会检测到本机DLL

  • 我不知道设置MSTest搜索路径的直接选项。您可以按照上面的建议使用procmon.exe确定搜索路径(它基本上是标准的Windows DLL搜索)

  • 默认的搜索路径并不包括启动目录,我认为这是造成混淆的原因。测试运行时,当前目录是测试结果“Out”目录,而不是MSTest启动目录

  • 但是,可以使用测试设置文件控制MSTest搜索行为(以及复制行为)。您可以通过Visual Studio轻松创建和编辑这些设置(请参见测试菜单),然后在MSTest命令行上指定创建的设置文件。您可以为Visual Studio和MSTest使用不同的设置文件

    通过这种方式,您可以准确地控制哪些DLL被复制到您的测试目录中。 请参阅以获取有关此的更多信息

    当然,DLL加载失败可能是由于缺少依赖项,并且错误消息中提到的DLL本身可能存在。您可以使用依赖项查看器或procmon来提取dll中意外的依赖项。

    Visual Studio 2017(可能还有2015年)提供了两种新方法来指示您的测试需要本机dll或其他文件,而无需测试设置文件:

    1:将dll的链接添加到测试项目,并告诉VS将其复制到输出目录。在解决方案资源管理器中的项目上单击鼠标右键,然后选择“添加”>“现有项”。浏览到7z.dll,单击“添加”按钮旁边的向下箭头,然后选择“添加为链接”。然后在解决方案资源管理器中选择新的7z.dll项,按alt Enter键打开属性,并将“复制到输出目录”设置为“如果更新则复制”(或“始终复制”)


    2:将
    DeploymentItemAttribute
    附加到测试类。此属性的构造函数采用单个字符串参数,该参数是要使类中的测试可用的文件的路径。它与测试项目的输出目录相关。

    您也设置了什么路径?如果是相对的,请将其更改为完全限定的路径名。相关帖子-此答案非常有用。对我来说,有效的方法是打开有问题的引用属性,选中“复制本地”,重建并看到它工作,然后我取消选中“复制本地”,从那时起它就继续工作。