Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assembly version conflicts for AutoFixture and Moq with NUnit on TeamCity 7

I previously had all unit tests for my solution contained in a single library, and were recently split out. When located in a single assembly, all tests passed both locally and on TeamCity, but when seperated there are version conflicts.

Config:

  • Team City 7.1.5 (build 24400)
  • AutoFixture 3.20.2
  • AutoFixture.AutoMoq 3.20.2
  • Moq 4.2.1402.2112
  • NUnit 2.6.3

I have several unit test assemblies, which all reference a base test library. All test assemblies use the NuGet packages listed above.

When running tests on a dev machine (VS 2015), all tests pass successfully.

When running a team city build, the following error is thrown:

System.IO.FileLoadException : Could not load file or assembly 'Moq, Version=4.1.1308.2120, Culture=neutral, PublicKeyToken=69f491c39445e920' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040) at Ploeh.AutoFixture.AutoMoq.MockPostprocessor.Create(Object request, ISpecimenContext context)

There is no reference to Moq 4.1.1308.2120 anywhere in my solution, so I know it must be a reference from AutoFixture.

Updating AutoFixture to 3.31.3 makes no difference.

I have the following Binding Redirect in the app.config files of all test assemblies:

<dependentAssembly>
  <assemblyIdentity name="Moq" publicKeyToken="69f491c39445e920" culture="neutral" />
  <bindingRedirect oldVersion="0.0.0.0-4.2.1402.2112" newVersion="4.2.1402.2112" />
</dependentAssembly>

I cannot downgrade my version of Moq to 4.1.1308.2120 as I use features of 4.2 in my tests.

It appears to me that Team City is ignoring the redirects. I have no idea why, and having tried every combination of version for these assemblies I cannot get Team City to run the tests successfully.

like image 738
Rob King Avatar asked Aug 19 '15 08:08

Rob King


2 Answers

We ran into this problem as well. We ran the assembly Fusion Logs on our build server and saw this in the error logs:

    Calling assembly : Ploeh.AutoFixture.AutoMoq, Version=3.50.2.0, Culture=neutral, PublicKeyToken=b24654c590009d4f.
===
LOG: This bind starts in default load context.
LOG: No application configuration file found.
LOG: Using host configuration file: 
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Post-policy reference: Moq, Version=4.1.1308.2120, Culture=neutral, PublicKeyToken=69f491c39445e920
LOG: GAC Lookup was unsuccessful.
LOG: Attempting download of new URL file:///D:/builds/13/s/AssessmentMigratorService.IntegrationPostbuild/bin/Debug/Moq.DLL.
LOG: Assembly download was successful. Attempting setup of file: D:\builds\13\s\AssessmentMigratorService.IntegrationPostbuild\bin\Debug\Moq.dll
LOG: Entering run-from-source setup phase.
LOG: Assembly Name is: Moq, Version=4.5.28.0, Culture=neutral, PublicKeyToken=69f491c39445e920
WRN: Comparing the assembly name resulted in the mismatch: Minor Version
ERR: The assembly reference did not match the assembly definition found.
ERR: Run-from-source setup phase failed with hr = 0x80131040.
ERR: Failed to complete setup of assembly (hr = 0x80131040). Probing terminated

So if you see this part of it

No application configuration file found.

what I think is happening is that the unit test runner host application on the build server is not seeing the application configuration file and so the assembly binding redirects are not able to apply, since they are in the app.config.

So I see 3 possible solutions/workarounds if you need to use these assemblies:

  1. Figure out why TeamCity's unit test runner on the build server cannot find the application configuration file and fix that.
  2. Use a different unit test runner on the build server.
  3. Add the binding redirects to the machine.config of the build server. That will apply globally on the entire machine, so there is no need for the redirects in the application configuration file at that point.
like image 176
Dan Csharpster Avatar answered Oct 01 '22 13:10

Dan Csharpster


I was embarrassed when I discovered the reason that I was seeing this error.

After 8 hours debugging I found that I had referenced TestProjectB in TestProjectA. Teamcity was set up to run any xunit against any Test*.dll that it found. So it found the TestProjectB.dll in TestProjectA's /bin/Debug folder.

But there is no TestProjectB.dll.config for TestProjectB.dll when it is in /TestProjectA/bin/Debug. Hence none of the assembly binding/redirect where being set.

I remove the project reference because it was unnecessary and updated my teamcity xunit runner to exclude dlls that don't have a matching config.

like image 30
Rhys Avatar answered Oct 01 '22 14:10

Rhys