chevron-thin-right chevron-thin-left brand cancel-circle search youtube-icon google-plus-icon linkedin-icon facebook-icon twitter-icon toolbox download check linkedin phone twitter-old google-plus facebook profile-male chat calendar profile-male
0 votes
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);
}
asked by allon.guralnek (10.6k points)

4 Answers

0 votes
Hi Allon,
Very strange indeed :? , can you please post the UnitMessageFactory class so that I can repo. it.
answered by scott (32k points)
0 votes
If I was able to create a repro solution, I would. Unfortunately, the UnitMessageFacotry class depends on ten other classes, each depending on ten other, etc. The dependency tree eventually encompasses half the solution. What do you suggest?
answered by allon.guralnek (10.6k points)
0 votes
ok,
send only the
static constructor
constructor
Factory
and
Factory.GetUnitFirmwareVersion


you can send it to support@typemock.com if you want.
answered by scott (32k points)
0 votes
Sorry for the delay. After additional refactoring the errors went away. The key thing I refactored which I believe was the cause of these errors was changing the singleton store, UnitMessageFactory.Factory, from a field to a property. Probably TypeMock encountered errors relating to not being able to mock fields. Perhaps the error messages could be improved, so the real source of the issue can be located quickly.
answered by allon.guralnek (10.6k points)
...