NDepend TypeInitializationExceptions when Testing with NUnit
So I'm trying to set up a project using the NDepend API for some metrics on my code (Which works nicely), however, when I attempt to run a testing framework (NUnit) over it, I'm getting TypeInitializationExceptions thrown.
Here is some code to reproduce the errors I'm getting:
Create a class library project, and reference the NDepend API dll at $NDependInstallPath$libNDependAPI
, setting copy local to false
. Create a class as follows:
public class NDependProjectLoader
{
public void LoadAnNDependProject()
{
var provider = new NDependServicesProvider();
}
}
Create a second class library project in the solution that will be your Test class. Reference NUnit and the project you created that references the NDependAPI
[TestFixture]
public class NDependProjectLoader_Tests
{
[Test]
public void I_can_load_an_depend_project()
{
new NDependProjectLoader().LoadAnNDependProject();
}
}
Build, and run the test using your test runner of choice (I've tried Resharper's test runner and the NUnit GUI).
You will get a TypeInitializationException on the line var provider = new NDependServicesProvider();
Looking inside that TypeInitializationException shows that the root exception's message is:
"{"Could not load file or assembly 'NDepend.Platform.DotNet' or one of its dependencies. The system cannot find the file specified.":"NDepend.Platform.DotNet"}".
Adding the AssemblyResolverHelper from the NDepend.PowerTools sample project and calling it as described in the getting started guide doesn't change the behaviour.
I /assume/ that the problem is related to this statement in the NDepend API getting started guide at http://www.ndepend.com/api/NDepend.API_gettingstarted.html
"The program executable assembly must be generated into $NDependInstallPath$"
In the case where the code is started from a test runner the executable will not be in the ndepend install path.
Calling NDependProjectLoader.LoadAnNDependProject() from a console application whose .exe is generated in $NDependInstallPath$lib (note that the .exe seems to need to be generated in the lib subfolder not in $NDependInstallPath$ as stated in the getting started guide) does not produce the exception, which further points to this being the cause.
So, the question is, how does one work with the NDepend API from anything other than a console application? For example, here I want to do so from a test runner. Another obvious candidate is an IIS application. Am I missing something obvious?
Indeed the problem comes from assembly resolution. You must tell the CLR where to find NDepend assemblies (ie in the dir $NDependInstallPath$Lib) You have 2 choices to do this. Suppose $NDependInstallPath$ is "C:NDepend" just for example:
Either edit AssemblyResolverHelper to resolve assemblies in "C:NDependLib"
Either create a App.Config file for your exe, add a <probing>
element that refers to "C:NDependLib". When the CLR won't resolve an assembly, then it'll look at dir in such element