是否可以在运行时加载相关程序集时运行单元测试

本文关键字:程序集 运行 单元测试 加载 运行时 是否 | 更新日期: 2023-09-27 17:51:00

是否可以运行单元测试,而不需要在依赖项上'本地复制',在运行时加载程序集?

更多细节:

我的。net解决方案如下:

  • MainProject (exe)[取决于'Class1Project',并在运行时使用'AssemblyLoaderProject'加载].

    'Class1Project'设置为'copy local = false'和'AssemblyLoaderProject'设置为'copy local = true'

  • Class1Project (dll)

  • AssemblyLoaderProject(在运行时使用AppDomain.CurrentDomain.AssemblyResolve和Assembly.LoadFrom加载和解析依赖程序集)

  • UnitTestsProject (Nunit或MSTest)

在单元测试项目中,我试图测试'Class1Project',我希望将其配置设置为与MainProject相同。

意思是,UnitTestProject也引用'Class1Project'与'copy local = false'和'AssemblyLoaderProject'与'copy local = true',并使用它在运行时加载程序集。

但由于某些原因,单元测试无法执行,运行程序抛出FileNotFoundException,指定它无法解析'Class1Project'程序集。

试图调试它,我看到测试运行器甚至没有得到告诉AssemblyLoaderProject加载程序集的代码。

测试代码看起来像这样:

[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void TestMethod1()
    {
        Loader.LoadAssemblies();
        Class1 cls = new Class1();
        Assert.IsTrue(true);
    }
}

这是我在MSTest上尝试用VS2012测试运行器调试它时得到的错误消息:

Test Name:  TestMethod1
Test FullName:  UnitTestProject1.UnitTest1.TestMethod1
Test Source:    c:'Users'user'Documents'Visual Studio 2012'Projects'ClassLibrary1'UnitTestProject1'UnitTest1.cs : line 13
Test Outcome:   Failed
Test Duration:  0:00:00.1177608
Result Message: 
Test method UnitTestProject1.UnitTest1.TestMethod1 threw exception: 
System.IO.FileNotFoundException: Could not load file or assembly 'ClassLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.=== Pre-bind state information ===
LOG: User = 'user
LOG: DisplayName = ClassLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
 (Fully-specified)
LOG: Appbase = file:///C:/Users/user/Documents/Visual Studio 2012/Projects/ClassLibrary1/UnitTestProject1/bin/Debug
LOG: Initial PrivatePath = NULL
Calling assembly : UnitTestProject1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:'PROGRAM FILES (X86)'MICROSOFT VISUAL STUDIO 11.0'COMMON7'IDE'COMMONEXTENSIONS'MICROSOFT'TESTWINDOW'vstest.executionengine.x86.exe.Config
LOG: Using host configuration file: 
LOG: Using machine configuration file from C:'Windows'Microsoft.NET'Framework'v4.0.30319'config'machine.config.
LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Attempting download of new URL file:///C:/Users/user/Documents/Visual Studio 2012/Projects/ClassLibrary1/UnitTestProject1/bin/Debug/ClassLibrary1.DLL.
LOG: Attempting download of new URL file:///C:/Users/user/Documents/Visual Studio 2012/Projects/ClassLibrary1/UnitTestProject1/bin/Debug/ClassLibrary1/ClassLibrary1.DLL.
LOG: Attempting download of new URL file:///C:/Users/user/Documents/Visual Studio 2012/Projects/ClassLibrary1/UnitTestProject1/bin/Debug/ClassLibrary1.EXE.
LOG: Attempting download of new URL file:///C:/Users/user/Documents/Visual Studio 2012/Projects/ClassLibrary1/UnitTestProject1/bin/Debug/ClassLibrary1/ClassLibrary1.EXE.
Result StackTrace:  at UnitTestProject1.UnitTest1.TestMethod1()

是否可以在运行时加载相关程序集时运行单元测试

假设Loader.LoadAssemblies是注册AssemblyResolve事件的方法,您将收到此异常,因为运行时无法通过探测找到ClassLibrary1.dll。理解为什么探查在这里起作用是很重要的。调用探测是因为在您可以通过Loader.LoadAssemblies加载任何程序集之前,必须对该方法进行jit。要正确地进行编译,运行时必须为编译时引用的类型加载程序集。由于您已将"copy local"设置为false,因此不会复制文件ClassLibrary1.dll并且不在探测路径中。因此,您的FileNotFoundException .

首先,我会尝试将Loader.LoadAssemblies移动到带有TestInitialize属性的方法中,以便在每次测试之前运行。然而,根据在测试执行之前复制文件的位置,这也可能不起作用。您可能必须在测试设置中启用部署,并使用DeploymentItem属性。

一个更大的问题是:如果你是单元测试,为什么你不能为依赖项设置"copy local"为true,这样它们就会被测试程序集复制?

根据Loader.LoadAssemblies的具体功能,您可能会遇到由于将程序集加载到多个或不同的加载上下文中而导致的其他问题。这可能会导致像InvalidCastException这样的问题,错误提示您不能将类型'X'转换为类型'X'。然而,你可能是安全的,因为AppDomain。如果没有通过探测找到程序集,将调用AssemblyResolve将其加载到load上下文中。

我同意应该有一种方法来配置解析目录,就像Mstest使用".runsettings"文件。

关于问题:

一个更大的问题是:如果你是单元测试,为什么你不能为依赖项设置"copy local"为true,这样它们就会被测试程序集复制?

嗯,答案是可能会使用很多依赖项的依赖项。

很难像第三方那样遵循所有被动依赖项。

我的意思是,如果你测试的组件依赖于组件A,那么A也可以依赖于组件B。copy local true将只复制A,但将在运行时失败,因为缺少B。考虑这样的情况:整个程序集嵌套在文件夹中,如

  • AppRoot
    • AppHost.exe
    • BuisnessLogic(文件夹)
    • 接口(文件夹)
    • UI(文件夹)
    • 基础设施(文件夹)
    • 3 rdparty(文件夹)

apphost有App.config,它允许目录探测,使运行时解析所有嵌套的目录。

最重要的"。runsetting "可以在单元测试期间配置类似的程序集探测。XUnit不能这样做。

一个解决方法是开始引用你的测试很多程序集,每一个你发现它不能被解决-但你发现它只有在运行测试。

这是一个糟糕而令人沮丧的解决方案。

我赞成插入一个更改请求,即XUnit也将支持目录探测配置。

那太好了。

(这实际上阻碍了我们从mstest升级到所需的XUnit)。

您必须使DLL' class1project '对加载器可用,因此,如果您不想将项目设置为总是复制它,您可以使用DeploymenItem属性来复制它用于测试,以便加载可以找到它。

VS2012测试运行器有一个bug。在我的项目中,我将所有依赖项设置为copy local = true,并且仍然有一些dll没有被复制到"Out"文件夹,使测试失败。如果我在VS2010下运行相同的测试,一切都运行完美。

使用DeploymentAttribute确实有帮助,但不应该是必需的。