Set entry assembly in Unit testing methods
Resolving null entry assembly issue in unit tests
Recently I started writing unit tests for a small project I keep in my visualstudio online TFS repository. After few test done I run into an issue.
Since this project heavily relies on Reflection and dynamic assembly loading, main class constructor at one point is calling
Assembly.GetEntryAssembly().Location
All classes for this project are in class library, so logically, there will be an app that will be host for class library assembly. I usually use simple console application for tests, which was the case for this project as well.
Somehow everything worked pretty well when I was testing from my test console app that was consuming class library, but when I started testing method from unit test I got Nullreference exception for the line of code mentioned above.
After debugging I noticed that Assembly.GetEntryAssembly() was returning null. It did not make much sense, but it turns put that entry assembly is not set when running from unit test framework.
For the moment it looked like a dead and to finish the test and the whole idea of writing unit tests for this project looked a little bit meaningless.
After some time googling I found a reference at link mentioned below in references links which is artificially setting entry point assembly value using reflection.
using System; using System.Collections.Generic; using System.Linq; using System.Reflection; namespace Application.Plugins.Testing { public class BaseTest { public BaseTest() { /* Preparing test start */ Assembly assembly = Assembly.GetCallingAssembly(); AppDomainManager manager = new AppDomainManager(); FieldInfo entryAssemblyfield = manager.GetType().GetField("m_entryAssembly", BindingFlags.Instance | BindingFlags.NonPublic); entryAssemblyfield.SetValue(manager, assembly); AppDomain domain = AppDomain.CurrentDomain; FieldInfo domainManagerField = domain.GetType().GetField("_domainManager", BindingFlags.Instance | BindingFlags.NonPublic); domainManagerField.SetValue(domain, manager); /* Preparing test end */ } } }
To make things easier and reusable, I stored the method in a class constructor and named it BaseTest.
Basically now every test class in Unit test project inherits this class, so entry assembly is set before any test method is run.
using System; using Microsoft.VisualStudio.TestTools.UnitTesting; using System.Reflection; namespace Application.Plugins.Testing { [TestClass] public class PluginTests:BaseTest { [TestMethod] public void ConstructorTest() { //Your test code here } } }
If your project at some point relies on Assembly.GetEntryAssembly() value, you might consider including this class and make all your test classes inherit this one.
References
Disclaimer
Purpose of the code contained in snippets or available for download in this article is solely for learning and demo purposes. Author will not be held responsible for any failure or damages caused due to any other usage.
Comments for this article