The Inquisitive Coder – Davy Brion's Blog

Trying to walk that thin line between intelligence and ignorance

yes that’s right, i AM mocking you!

Posted by Davy Brion on January 6th, 2008

Up until now, i’ve always written my stubs and (simple) mocks myself… But now i needed to test the interaction between two classes and i really didn’t feel like writing the mock and the verification logic myself again, so i figured it was time to finally learn how to use a real mocking framework. I picked Ayende’s Rhino Mocks, mainly because i find myself agreeing a lot with the stuff he says… so i figured his mocking framework would be a pretty safe bet.

Anyway, so i needed to test the interaction between two classes. I have the following interface:

    public interface ICheckClassMapping : ICheck

    {

        ICollection<ClassMapping> Select(ICollection<ClassMapping> classMappings);

        void Check(ClassMapping classToCheck, MetaDataStore store);

    }

And then i have a class which has to interact with instances of the ICheckClassMapping interface. This class first needs to call the Select method and pass a collection of ClassMappings to it. Each ClassMapping in the returned collection of ClassMappings must be passed to the Check method. Any ClassMapping which was not returned by Select can not be passed to the Check method. So when i wanted to write a test for this, i really didn’t feel like writing this kind of mock myself. Enter Rhino Mocks… This is the result:

        [Test]

        public void Run_StoreHasThreeClassMappingsAndCheckReturnsTwo_OnlySelectedMappingsAreChecked()

        {

            MappingMetaDataStore mappingStore = new MappingMetaDataStore();

            MetaDataStore store = new MetaDataStore(null, mappingStore);

 

            ClassMapping c1 = TestMappingFactory.CreateClassMapping(MappingSettings.Defaults, “c1″);

            ClassMapping c2 = TestMappingFactory.CreateClassMapping(MappingSettings.Defaults, “c2″);

            ClassMapping c3 = TestMappingFactory.CreateClassMapping(MappingSettings.Defaults, “c3″);

            mappingStore.AddClassMappings(c1, c2, c3);

 

            MockRepository mockRepository = new MockRepository();

            ICheckClassMapping check = mockRepository.CreateMock<ICheckClassMapping>();

            Expect.Call(check.Select(mappingStore.ClassMappings)).Return(new List<ClassMapping>() { c1, c3 });

            Expect.Call(delegate { check.Check(c1, store); });

            Expect.Call(delegate { check.Check(c3, store); });

            mockRepository.ReplayAll();

 

            new CheckClassMappingRunner().Run(check, store, null);

            mockRepository.VerifyAll();

        }

The first couple of lines just set up the MetaDataStore with 3 ClassMappings… And then comes the interesting part:

            MockRepository mockRepository = new MockRepository();

            ICheckClassMapping check = mockRepository.CreateMock<ICheckClassMapping>();

Here we create the MockRepository and create a mock object that implements our ICheckClassMapping interface. This will generate a type at runtime that implements the interface and return an instance of that type to us. Now it’s time to specify what we expect of our mock:

            Expect.Call(check.Select(mappingStore.ClassMappings)).Return(new List<ClassMapping>() { c1, c3 });

            Expect.Call(delegate { check.Check(c1, store); });

            Expect.Call(delegate { check.Check(c3, store); });

The first thing i expect of my mock is that its Select method is called and that it will receive the defined ClassMappings as its parameter. Then we instruct the mock to return a new list of ClassMappings containing only the first and third ClassMapping.
After that, we specify that we expect the mock’s Check method to be called with the first ClassMapping instance as a parameter, together with the store variable. And then we expect the same but with the third ClassMapping instance.

Then we instruct the MockingRepository to switch all known mocks (in this case, just one) to ‘replay’ mode:

            mockRepository.ReplayAll();

This basically means that the mock will replay the expectations we set on it as it’s being used by our code.

After that, we call the method we’re actually testing and then we ask the MockingRepository to verify that our expectations are correct:

            new CheckClassMappingRunner().Run(check, store, null);

            mockRepository.VerifyAll();

This works great… i kinda feel stupid for only learning this now :)

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>