Failure to resolve assembly with Mono.Cecil from jenkins

310 views Asked by At

In my solution, I am writing a unit test with NUnit that uses Mono.Cecil.

The concept is pretty simple: I have three assemblies ASource, ATest, ATestUtils.

  1. ASource: Contains a class "MyClass" that I want to test. (The assembly references other assemblies.)
  2. ATest: Contains the unit test that tests "MyClass" in ASource.
  3. ATestUtils: References Mono.Cecil an provides utility methods to - I keep it simple to give an example - returns all the property names of an input type (I know, I do not need Mono.Cecil to do that, but it is just an example here).

In my ATestUtils, I load the assembly ASource like so:

// In ATestUtils
public static IEnumerable<PropertyDefinition> GetPropertiesFromType(Type typeOfClass)
{
    var ass = AssemblyDefinition.ReadAssembly(typeOfClass.Assembly.Location);
    var refs = ass.MainModule.ImportReference(typeOfClass);
    var typeDef = refs.Resolve();
    
    return typeDef.Properties;
}

When I run my unit test "MyUnitTest" using that method from ATestUtils on my local machine (debug and release), it works fine. When it is executed on my jenkins , it gives the following Error:

Error : ATest.MyUnitTestClass.MyUnitTest

Mono.Cecil.AssemblyResolutionException : Failed to resolve assembly: 'ASource, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'
   bei Mono.Cecil.BaseAssemblyResolver.Resolve(AssemblyNameReference name, ReaderParameters parameters) in C:\src\cecil\Mono.Cecil\BaseAssemblyResolver.cs:Zeile 122.
   bei Mono.Cecil.BaseAssemblyResolver.Resolve(AssemblyNameReference name) in C:\src\cecil\Mono.Cecil\BaseAssemblyResolver.cs:Zeile 117.
   bei Mono.Cecil.DefaultAssemblyResolver.Resolve(AssemblyNameReference name) in C:\src\cecil\Mono.Cecil\DefaultAssemblyResolver.cs:Zeile 33.
   bei Mono.Cecil.MetadataResolver.Resolve(TypeReference type) in C:\src\cecil\Mono.Cecil\MetadataResolver.cs:Zeile 110.
   bei Mono.Cecil.ModuleDefinition.Resolve(TypeReference type) in C:\src\cecil\Mono.Cecil\ModuleDefinition.cs:Zeile 748.
   bei Mono.Cecil.TypeReference.Resolve() in C:\src\cecil\Mono.Cecil\TypeReference.cs:Zeile 280.
   bei ATestUtils.TestTools.GetPropertiesFromType(Type typeOfClass) in D:\Hudson\workspace\MyBranchName\MyProject\ATestUtils\TestTools.cs:Zeile 47.
   bei ATest.MyUnitTestClass.MyUnitTest()

I checked the path "typeOfClass.Assembly.Location" on my jenkins and I am very certain that the dll was created and exists during the test step of my jenkins.

I have a feeling that I have not yet understood how to correctly load assemblies with Mono.Cecil. Is it possible that my project ATest cannot be loaded correctly on the jenkins because it has dependencies to other assemblies? Do I have to load them "somehow" as well? If so how? And why is it working on my local machine then?

My environment:

  • Visual Studio 2022 v17.6.3

  • Mono.Cecil v0.11.5

  • NUnit v3.13.3

  • NUnit3TestAdapter v4.5.0.

  • Jenkins v2.401.1, using a jenkins script (pipeline syntax), bs.Windows10.amd64, the test step executes a powershell script that executes the unit tests using NUnit.Console 3.12.0 and opencover.4.7.1221

I am grateful for any help. If more information is needed to answer the question, I will be happy to provide it.

1

There are 1 answers

0
AppDeveloper On

You must describe the example in more detail, please. As far as I understand, you pass a type from the ASource assembly to the GetPropertiesFromType method. I assume the type is not NULL. In this case typeOfClass.Assembly.Location should also give you the correct location and the assembly should be loaded. Now I don't understand why you import the passed type again? You know that this type is included in the assembly. I would therefore write the following:

var typeDef = ass.MainModule.Types.SingleOrDefault(x => x.FullName == typeOfClass.FullName);

Also, I assume that you meant an IEnumerable<PropertyDefinition> as the return type of the GetPropertiesFromType method?

If my assumptions are correct and the assembly ASource is configured as a project reference in ATest, my unit test will run successfully.

[Test]
public void Test1()
{
    var props = MyUtil.GetPropertiesFromType(typeof(MyClass));
    foreach (var prop to props)
    {
        Assert.That(prop, Is.Not.Null);
    }
}

Is your assembly referenced in your Unit Test assembly? And are all assemblies referenced by ASource also copied so that ATest can find them?