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 chased my tail on this one for probably about an hour. I have a helper method to set up some fakes. I was have a test fail that shouldn't of been and would only fail when ran in a particular order. It was obvious once I figured it out (a previous test didn't have the Isolated attribute), but finding it was a pain.

I'd propose a feature (since you're using Aspects and reflection heavily everywhere anyway), that if you make a call to something in Isolate class, that the calling method (or somewhere in the calling stack methods), must have the attribute of 'Isolated' applied.

Here's a demo of what I did to myself (very simplified, the real world this was buried) that got me in trouble:

Class under test:
    public class SomeClassWithOneReturnMethod
    {
        public string WillReturnAString(string notUsed)
        {
            return "TEST";
        }
    }


Tests - individually they both pass:
        [TestMethod()]
        public void Test1()
        {
            //Arrange
            SomeClassWithOneReturnMethod fake = Isolate.Fake.Instance<SomeClassWithOneReturnMethod>();
            Isolate.WhenCalled(() => fake.WillReturnAString(null)).WillReturn("ABC");
            Isolate.Swap.NextInstance<SomeClassWithOneReturnMethod>().With(fake);
            //Because in real world we may go down a code path where another instance of fake might
            //be created (depending on logic) and we want to make sure it returns ABC also
            Isolate.Swap.NextInstance<SomeClassWithOneReturnMethod>().With(fake);

            //Act
            SomeClassWithOneReturnMethod target = new SomeClassWithOneReturnMethod();
            string test = target.WillReturnAString(null);

            //Assert
            Assert.AreEqual<string>("ABC", test);
        }

        [Isolated(), TestMethod()]
        public void Test2()
        {
            //Arrange
            SomeClassWithOneReturnMethod fake = Isolate.Fake.Instance<SomeClassWithOneReturnMethod>();
            Isolate.WhenCalled(() => fake.WillReturnAString(null)).WillReturn(null);
            Isolate.Swap.NextInstance<SomeClassWithOneReturnMethod>().With(fake);
            //Because in real world we may go down a code path where another instance of fake might
            //be created (depending on logic) and we want to make sure it returns ABC also
            Isolate.Swap.NextInstance<SomeClassWithOneReturnMethod>().With(fake);

            //Act
            SomeClassWithOneReturnMethod target = new SomeClassWithOneReturnMethod();
            string test = target.WillReturnAString(null);

            //Assert
            Assert.AreEqual<string>(null, test);
        }


But if you set up an ordered test where the first test is Test1 and the second test is Test2, the second test will fail because 'ABC' will be returned instead of null (because the clean up code for Test1 never ran meaning the swap next instance for the 2nd call was still valid).
asked by boo (21.8k points)

3 Answers

0 votes
Brian,

It's interesting. Would you fail the test with a descriptive warning?
answered by gilz (14.5k points)
0 votes
Yes, I would fail the test with a message.

Similar to the warning you get when you try to Verify.WasCalled on a static method but you didn't first fake all static methods in order for that to occur.

It's a quick simple way to keep people from making a rookie mistake. Now whether it's quick and simple from your end...that's another story right? :)
answered by boo (21.8k points)
0 votes
Actually...

Well, we'll write it up on the board. Thanks for the suggestion!
answered by gilz (14.5k points)
...