I have an odd problem I haven't been able to reproduce outside our solution. I have changed a static method of a singleton class to an instance method, and corrected all usages of it. This caused one test (out of 817) to fail. The test class doesn't have [ClassInitialize] or [TestInitialize], and is marked with [Isolated]. The test is below:
[TestMethod]
public void UnitReadAllParametersMessage_Version5358()
{
Isolate.Fake.Instance<UnitMessageFactory>(Members.CallOriginal, ConstructorWillBe.Called); // Workaround for TypeMock bug: http://forums.typemock.com/viewtopic.php?f=9&t=4975
Isolate.WhenCalled(() => UnitMessageFactory.Factory.GetUnitFirmwareVersion(0)).WillReturn(5359); // *** Exception thrown here ***
var msgs = MessageFactory.UnitReadAllParametersMessage(306550, 256);
Assert.AreEqual(2, msgs.Count);
}
The test fails with the following exception:
Test method GRT.Framework.Protocol.Factory.UnitTests.MessageFactoryReadAllTest.UnitReadAllParametersMessage_Version5358 threw exception:
System.ArgumentException: An item with the same key has already been added.
at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
at ip.e(hk A_0)
at gz.a(Type A_0, Constructor A_1, Object A_2, Boolean A_3)
at gz.a()
at ev.a()
at gi.a(Type A_0, Object A_1, MethodBase A_2, String A_3, TypeParams A_4)
at gi.a(Object A_0, String A_1, String A_2, MethodBase A_3, Object[] A_4, Object A_5)
at GRT.Framework.Protocol.Unit.Factory.UnitMessageFactory.GetUnitFirmwareVersion(UInt32 unitID) in UnitMessageFactory.cs: line 153
at GRT.Framework.Protocol.Factory.UnitTests.MessageFactoryReadAllTest.<UnitReadAllParametersMessage_Version5358>b__0() in MessageFactoryReadAllTest.cs: line 30
at TypeMock.MockManager.a(String A_0, String A_1, Object A_2, Object A_3, Boolean A_4, Boolean A_5, Object[] A_6)
at TypeMock.InternalMockManager.getReturn(Object that, String typeName, String methodName, Object methodParameters, Boolean isInjected, Boolean isInterceptedType)
at GRT.Framework.Protocol.Factory.UnitTests.MessageFactoryReadAllTest.UnitReadAllParametersMessage_Version5358() in MessageFactoryReadAllTest.cs: line 28
If I remove the last two lines from the test (thus leaving only Isolate calls), nothing changes. If I then remove the first line of test (the bug workaround), I get a different exception message (still being thrown from the same line, the WhenCalled):
Test method GRT.Framework.Protocol.Factory.UnitTests.MessageFactoryReadAllTest.UnitReadAllParametersMessage_Version5358 threw exception:
TypeMock.TypeMockException:
*** No method with name UnitReadAllParametersMessage_Version5358>b__0 in type GRT.Framework.Protocol.Factory.UnitTests.MessageFactoryReadAllTest exists.
at ge.b(Type A_0, String A_1)
at ey.a(Mock A_0, Object A_1, MethodBase A_2, Object A_3, Object[] A_4)
at gi.a(Object A_0, String A_1, String A_2, MethodBase A_3, Object[] A_4, Object A_5)
at GRT.Framework.Protocol.Factory.UnitTests.MessageFactoryReadAllTest.<UnitReadAllParametersMessage_Version5358>b__0() in MessageFactoryReadAllTest.cs: line 30
at TypeMock.MockManager.a(String A_0, String A_1, Object A_2, Object A_3, Boolean A_4, Boolean A_5, Object[] A_6)
at TypeMock.InternalMockManager.getReturn(Object that, String typeName, String methodName, Object methodParameters, Boolean isInjected, Boolean isInterceptedType)
at GRT.Framework.Protocol.Factory.UnitTests.MessageFactoryReadAllTest.UnitReadAllParametersMessage_Version5358() in MessageFactoryReadAllTest.cs: line 28
I checked with ILSpy, and the compiler-generated lambda method does in fact exist with that exact name.
The interesting part is that if I copy-paste this same test multiple times, changing the test method names, only the first test or every run fails. If I mark it with [Ignore], the next test which is run first in that class fails. All other tests except the first test pass. If I [Ignore] the whole class, then a test in a different test class that performs the same WhenCalled faking of GetUnitFirmwareVersion fails. I have been unable to track down the dependency. If I turn the method 'GetUnitFirmwareVersion' back into a static method (and change back all usages), all tests pass. Faking another instance method of the same class also fails. Faking instance or static methods of a different class works. Not using chaining inside WhenCalled (by putting the singleton instance of UnitMessageFactory.Factory inside a temporary variable and using WhenCalled on it) doesn't help.
Do you have any idea what is happening, or have any clues as to what is going on? I am stumped, and currently forced to add the following test method just to swallow the first exception and allow the rest of the tests to pass:
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void AAA_RunFirst()
{
Isolate.Fake.Instance<UnitMessageFactory>(Members.CallOriginal, ConstructorWillBe.Called);
Isolate.WhenCalled(() => UnitMessageFactory.Factory.GetUnitFirmwareVersion(0)).WillReturn(5359);
}