Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to run unit tests when loading dependent assemblies at run-time?

Is it possible to run unit tests without 'copy local' on the dependencies, loading the assemblies in run-time?

More details:

My .net solution looks like this:

  • MainProject (exe) [depends on 'Class1Project' and load it at runtime using 'AssemblyLoaderProject'].

    'Class1Project' set to 'copy local = false' and 'AssemblyLoaderProject' set to 'copy local = true'

  • Class1Project (dll)

  • AssemblyLoaderProject (load and resolve dependencies assemblies at runtime using AppDomain.CurrentDomain.AssemblyResolve and Assembly.LoadFrom)

  • UnitTestsProject (either Nunit or MSTest)

In the unit tests project i'm trying to test 'Class1Project' and i wish to set its configuration the same as MainProject.

Meaning, the UnitTestProject also reference 'Class1Project' with 'copy local = false' and 'AssemblyLoaderProject' with 'copy local = true', and use it to load assemblies in runtime.

But for some reason the unit tests could not execute, the runner throw FileNotFoundException specifing that it couldn't resolve the 'Class1Project' assembly.

Trying to debug it and i see that the test runner doesn't even get to the code that tell AssemblyLoaderProject to load the assemblies.

The test code looks like this:

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

This is the error message i get when trying to debug it with VS2012 test runner on MSTest:

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()
like image 554
avivr Avatar asked Dec 19 '25 23:12

avivr


1 Answers

Assuming Loader.LoadAssemblies is the method that signs up for the AssemblyResolve event, you are receiving this exception because the runtime cannot find ClassLibrary1.dll via probing. It is important to understand why probing is coming into play here. Probing is invoked because before you can load the any assemblies via Loader.LoadAssemblies the method must be Jitted. To be properly jitted, the runtime must load the assemblies for types referenced at compile-time. Since you have turned 'copy local' to false the file ClassLibrary1.dll is not copied and not in the probing path. Hence, your FileNotFoundException.

First, I would try moving Loader.LoadAssemblies into a method marked with the TestInitialize attribute to run before each test. However, depending on the where the files are copied before test execution, this may not work either. You may have to enable deployment in the test settings and use the DeploymentItem attribute.

A bigger question is: If you are unit testing, why can't you set 'copy local' to true for the dependencies so they are copied with the test assemblies?

Depending on exactly what Loader.LoadAssemblies does, you may encounter other issues caused by assemblies being loaded into multiple or different load contexts. This can cause problems like InvalidCastException where the error says you cannot cast type 'X' to type 'X'. However, you may be safe because AppDomain.AssemblyResolve will be called to load an assembly into the Load context if it is not found via probing.

like image 196
Mike Zboray Avatar answered Dec 22 '25 11:12

Mike Zboray