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
Welcome to Typemock Community! Here you can ask and receive answers from other community members. If you liked or disliked an answer or thread: react with an up- or downvote.
0 votes
I comprised this reproduction from real code. You will have to take for granted that in the real code this would be a valid test; this just demonstrates the bug.

Classes under test:
    public class OwningObject
        public OwningObject()
            SomeList = new List<CollectionObjectType>();
        public List<CollectionObjectType> SomeList { get; set; }

    public class CollectionObjectType
        public string Message { get; set; }

Test that demonstrates the bug:
        [Isolated(), TestMethod()]
        public void TestWhereYouNeedToFakeObjectButUseListWithCallsOriginal()
            OwningObject target = Isolate.Fake.Instance<OwningObject>(Members.ReturnRecursiveFakes);
            Isolate.WhenCalled(() => target.SomeList).CallOriginal();

            //Thankfully setter isn't private otherwise I don't know how we would do this!
            Isolate.WhenCalled(() => { target.SomeList = null; }).CallOriginal();  
            target.SomeList = new List<CollectionObjectType>();
            //Has to be called after we manually initialize property in above lines
            Assert.AreEqual<int>(0, target.SomeList.Count);
            Isolate.WhenCalled(() => target.SomeList.Add(null)).CallOriginal();
            //Because of Isolateor CallOriginal bug
            Assert.AreEqual<int>(1, target.SomeList.Count);

            //Act - some method that will be adding a value to the list through the owning object
            target.SomeList.Add(new CollectionObjectType() { Message = "TEST" });

            Assert.AreEqual<int>(1, target.SomeList.Count);
            Assert.AreEqual<string>("TEST", target.SomeList[0].Message);

Bug - Isolator shouldn't need to RUN the code in order to mark that the original should be called. We know that it is being ran because if we remove the 'target.SomeList.Clear()' line we'll have 2 items in the list when we assert for 1. We can also tell this because of the line I added that asserted that after adding the CallOriginal code we have an item in the list and before CallOriginal we had 0. Without the CallOriginal the functionality of Add will not work because of ReturnRecursiveFakes. In real world test that this is modeled after we need ReturnRecursiveFakes for all the other properties that are examined in the test so it's not an option to not use ReturnRecursiveFakes
asked by boo (21.8k points)

4 Answers

0 votes
Hi Boo,

The problem you're seeing could result from an issue we've found in version 5.3 - I'll send a patch so we can check if it solves the problem.
answered by dhelper (11.9k points)
0 votes
Hi Brian,

The test should have throw an exception because you are trying to fake mscorlib method here:
Isolate.WhenCalled(() => target.SomeList.Add(null)).CallOriginal();

The Add method belongs to List<T> class which is defined in mscorlib.dll
Currently we can not identify that SomeList property returns mscorlib type so the Add method is actually invoked and add null to the list.

This issue will be solved once we'll add the ability to fake mscorlib collections.
answered by ohad (35.5k points)
0 votes
Hi there.

I think I ran to the same problem where WhenCalled actually runs the code itself..

Do you have any fix for that already / workaround?

answered by benb (720 points)
0 votes
Hi Ben,

The code inside add is called beacuse Isolator deos not recognize it. The reason that the Add implementation is inside MsCorLib. if you overload the Add Method inside your derived class the problem will be solved.
answered by dhelper (11.9k points)