Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Visual Studio 2015 InvalidProgramException in Unit Test With Fakes

I am using Visual Studio 2015 Enterprise RTM to write unit tests for a project that uses Unity Container.

I have discovered that the simple act of adding a fakes assembly for Unity, not even actually using the fake, is sufficient to generate this exception:

System.InvalidProgramException: Common Language Runtime detected an invalid program.



Consider the following steps to reproduce:

  • Using Visual Studio 2015 Enterprise RTM create a Unit Test project targeting .NET 4.6

  • Add the NuGet package "Unity" version 3.5.1404.0

  • Add the NuGet package "CommonServiceLocator" version 1.2.0

  • Write a single unit test like so:

[TestClass]
public class UnitTest1 : IDisposable
{
    [TestMethod]
    public void TestMethod1()
    {
        new ResolvedArrayParameter<IDisposable>(new IDisposable[] {this});
    }

    void IDisposable.Dispose()
    {
    }
}
  • Verify the test passes

  • Right click on the Microsoft.Practices.Unity reference and choose "Add Fakes Assembly"

  • Re-run the test

  • Observe the following remarkable test failure:

Test Name: TestMethod1
Test FullName: UnitTestProject11.UnitTest1.TestMethod1
Test Source: c:\temp\UnitTestProject11\UnitTestProject11\UnitTest1.cs : line 12
Test Outcome: Failed
Test Duration: 0:00:00.0572447

Result StackTrace:

at Microsoft.Practices.Unity.ResolvedArrayParameter..ctor(Type arrayParameterType, Type elementType, Object[] elementValues)
at Microsoft.Practices.Unity.ResolvedArrayParameter`1..ctor(Object[] elementValues)
at UnitTestProject11.UnitTest1.TestMethod1() in c:\temp\UnitTestProject11\UnitTestProject11\UnitTest1.cs:line 13
Result Message:
Test method UnitTestProject11.UnitTest1.TestMethod1 threw exception:
System.InvalidProgramException: Common Language Runtime detected an invalid program.



The most extraordinary feature of this problem is evidently fakes don't even need to appear directly in the code for the failure to manifest.

An extensive amount of fiddling reveals that retargeting the test project to .NET 4.5 "fixes" the problem, which is a non-starter for me because of another issue I posted some weeks back.

Even more fiddling with virtually all fakes settings (code contracts, etc.) yielded no solution.

Any advice on this issue would be very much appreciated.

like image 536
42vogons Avatar asked Sep 24 '15 18:09

42vogons


People also ask

How do I automate unit testing in Visual Studio?

To generate unit tests, your types must be public. Open your solution in Visual Studio and then open the class file that has methods you want to test. Right-click on a method and choose Run IntelliTest to generate unit tests for the code in your method. IntelliTest runs your code many times with different inputs.


1 Answers

The only general solution is to make sure that all parts match the version of CLR you are using very closely and that VS has the latest updates.

There is no magic bullet for this problem. You need to know (dig out) the exact CLR version compatibility of all parts that are connected in your project when you inject fakes. Mind you that "compatibility" might be just the matter of manifest but more frequently they are the matter of nuances of how was/is the final code generated and for which version of the virtual machine.

These things normally don't matter for running and debugging since there are several layers that make sure that minor version differences either don't matter or you get a silent switch to whatever your code is declared to be compatible with.

But, when you use Fakes, the "system" injects raw code into your (which includes 3rd party libraries involved) and that means that it skips most checks - couldn't work otherwise. But, when the time comes to actually run the code, the engine (virtual machine) has to do some checks for it's own safety/integrity and it tends to get paranoid and bail out if it looks like declarations don't match closely enough.

This is the reason why someone asked whether assemblies involved are strongnamed or signed. That's the only level of guarantee that "system" will really trust. Without that it will do a degree of guessing and while it mostly doesn't matter for normal runs if matters a lot for code injection.

I'm still not talking possible real problems - this is all assuming that actual code is fine and just declarations are confused. You could try to play with that but it would take a lot of time and effort. Much easier to go checking if you can get versions of assemblies that are better matching.

The fact that errors vanished when you switched your flavor back to 4.5 tells you that either some of the assemblies involved are not "close enough" for 4.6 or there can be some glitches with code injection that were fixed by updates you haven't taken in yet.

Yes it involves a lot of pain but that's the price of wanting to be at the frontier.

like image 149
Pera Avatar answered Oct 04 '22 21:10

Pera