KoffeeKoder






  • If you are new to mocking then I highly recommend reading my previous post in which I introduced the basics of mocking. If you are more interested in watching a screen casts then watch Introduction to Mocking.

    In this post I am going to explain the differences between CreateMock, DynamicMock and PartialMock.

    When you use CreateMock to create a mock object then you are creating a very strict mock object that have to follow certain rules. This means that it will only do what it is told no more and no less. Let’s take a simple example. We need to build a page which will add a customer. We will be using the MVP pattern to build our application. Let’s first take a look at the view.


    public interface IAddCustomerView
        {
            string FirstName { get; }
            string LastName { get; }
            string Message { set; }
        }


    We will also have a repository which will create the customer. Here is the ICustomerRepository interface.


    public interface ICustomerRepository
        {
            void Add(Customer customer);
        }


    Now, let’s take a look at the presenter which uses the view and the repository to perform action on the view.


    public class AddCustomerPresenter
        {
            private IAddCustomerView _view;
            private ICustomerRepository _repository;

            public AddCustomerPresenter(IAddCustomerView view, ICustomerRepository repository)
            {
                _view = view;
                _repository = repository;
            }

            public void AddCustomer()
            {
                Customer customer = new Customer();
                customer.FirstName = _view.FirstName;
                customer.LastName = _view.LastName;

                _repository.Add(customer);

                if(customer.Id > 0)
                     _view.Message = "Customer has been inserted";
                else _view.Message = "Not Inserted";             
            }
        }


    The AddCustomer method is responsible for creating a new customer object and then passing it to the repository for the actual insert operation. If the customer is inserted then the id of the customer is changed and hence the message “Customer has been inserted” is assigned to the message property of the view.

    The unit test looks something like the following:


    [TestFixture]
        public class when_customer_is_added
        {
            private AddCustomerPresenter _presenter;
            private ICustomerRepository _repository;
            private IAddCustomerView _view;
            private MockRepository _mocks;
            

            [SetUp]
            public void initialize()
            {
                _mocks = new MockRepository();
                _view = _mocks.CreateMock<IAddCustomerView>();
            }
                 

            [Test]
            public void should_set_the_successfull_message()
            {
                _presenter = new AddCustomerPresenter(_view, new CustomerRepositoryStub());

                using (_mocks.Record())
                {
                    SetupResult.For(_view.FirstName).Return("mohammad");
                    SetupResult.For(_view.LastName).Return("azam");

                    Expect.Call(_view.Message = "Customer has been inserted");
                    
                }

                using (_mocks.Playback())
                {
                    _presenter.AddCustomer();
                }

            }
        }


    There is couple of important things about this unit test. First we are using the CreateMock to create a mock object. This means that our mock object will behave exactly as we will expect it to behave. Second we are using CustomerRepositoryStub as an ICustomerRepository. This is because the CustomerRepository needs to perform action on the customer object. This can only be simulated by using a stub. Here is the implementation of the stub.


    public class CustomerRepositoryStub : ICustomerRepository
        {   

            public void Add(Customer customer)
            {            
                customer.Id = 12;
            }
           
        }


    The only function of the CustomerRepositoryStub is to change the customer id so that the message property can be set appropriately.

    If you run the above test it will pass. Now, let’s make a small change in your presenter code. We will add only one line which assigns the view some dummy text.


    public void AddCustomer()
            {
                Customer customer = new Customer();
                customer.FirstName = _view.FirstName;
                customer.LastName = _view.LastName;

                _view.Message = "foo";

                _repository.Add(customer);

                if(customer.Id > 0)
                     _view.Message = "Customer has been inserted";
                else _view.Message = "Not Inserted";             
            }


    If you run the above test then it will fail. This is because the CreateMock creates a strict mock that should only perform what is described in the expectations. You can easily pass the test by making a DynamicMock. Take a look at the code below:


      [SetUp]
            public void initialize()
            {
                _mocks = new MockRepository();
                _view = _mocks.DynamicMock<IAddCustomerView>();
            }
     

    DynamicMock will create weak mock which means that it expects you to fulfill the   expectations but if you trigger some other methods then it will not blow up on you. It DynamicMock is like a good teacher who does not get mad if you do extra chapters which were not included in the assignment.

    Let’s move to PartialMock. PartialMocks can be used to create a mock object of a concrete class. Keep one thing in mind that you can only call virtual methods of the concrete class. Here is a simple example.


    public class CustomerArchiveService
        {
            public virtual void Foo()
            {

            }

            public virtual bool Archive(Customer customer)
            {
              

                return false;
            }
        }


    The CustomerArchiveService does not have an interface hence we will use PartialMock to mock the concrete class.


    [SetUp]
            public void initialize()
            {
                _mocks = new MockRepository();

                _view = _mocks.DynamicMock<IArchiveCustomerView>();
                _service = _mocks.PartialMock<CustomerArchiveService>();
            }

    [Test]
            public void should_display_successfull_message()
            {
                _presenter = new ArchiveCustomerPresenter(_view, _service);

                using (_mocks.Record())
                {
                    SetupResult.For(_view.FirstName).Return("Mohammad");
                    SetupResult.For(_view.LastName).Return("Azam");

                    Expect.Call(_service.Archive(null)).IgnoreArguments().Return(true);
                    Expect.Call(_view.Message = "Archived");
                }

                using (_mocks.Playback())
                {
                    _presenter.Archive();
                }
            }



    Hope you liked the post!



  • by Ben Scheirman on 10/19/2008 7:18:35 PM
  • You should really be advocating the use of the new AAA syntax (Arrange, Act, Assert) in RhinoMocks 3.5.

    it looks like this:

    var mockView = MockRepository.GenerateMock();

    mockView.Stub(x=>x.CustomerName).Return("joe");

    ...

    mockView.AssertWasCalled(x=>x.Message = "...");
  • by Mohammad Azam on 10/19/2008 7:22:06 PM
  • Hi Ben,

    Thanks! I will surely check it out.