Click here to Skip to main content
15,861,172 members
Articles / Programming Languages / C#
Article

Introduction to Mocking

Rate me:
Please Sign up or sign in to vote.
4.50/5 (24 votes)
23 Oct 2008CPOL3 min read 131.9K   1.4K   53   5
In this article we will explain mocking and different benefits that we can achieve by introducing mocking in our unit tests.

Introduction

Mocking is an integral part of unit testing. Although you can run your unit tests without use of mocking but it will drastically slow down the executing time of unit tests and also will be dependent on external resources. In this article we will explain mocking and different benefits that we can achieve by introducing mocking in our unit tests.

Real World Example

We will focus on a real world example so that you will get a good grasp of mocking. Let’s say we are working on banking software which pulls out the customer balance information from some database. The software also makes a request to an external web service for authentication. The process of authentication is slow since it involves many different steps including discovering the web service, serializing the input and output parameters etc.

We want to test that if the customer balance returned is correct or not.

Here is our web service with the Authenticate method:

C#
public class AverageJoeBankService : IAverageJoeBankService
    {
        public bool Authenticate(string userName, string password)
        {
            // This is just simulate the time taken for the web service to authenticate! 
            System.Threading.Thread.Sleep(5000); 
            return true; 
        }     
    }

As you can see, we are simply simulating the Authenticate method. We are assuming that it will take at least 5 seconds to authenticate the user. Of course in real application your Authenticate method will communicate with the real web service.

And here is the AccountBalanceService method:

C#
public class AccountBalanceService
    {
        private IAverageJoeBankService _averageJoeService;

        public AccountBalanceService(IAverageJoeBankService averageJoeService)
        {
            _averageJoeService = averageJoeService;
        }

        public double GetAccountBalanceByUser(User user)
        {       
            // the authenticate method below takes too much time! 
            bool isAuthenticated = _averageJoeService.Authenticate(user.UserName,
                user.Password);

            if (!isAuthenticated)
                throw new SecurityException("User is not authenticated"); 
            
            // access database using username and get the balance 

            return 100;      
        }
    }

Here is our first attempt to write the unit tests:

C#
[Test]
public void should_be_able_to_get_the_balance_successfully_without_using_mock_objects()
{
    User user = new User();
    user.UserName = "johndoe";
    user.Password = "johnpassword";

    _accountBalanceService = new AccountBalanceService(new AverageJoeBankService());

    Assert.AreEqual(100, _accountBalanceService.GetAccountBalanceByUser(user));
}

In the unit test above we are simply using the concrete implementation of the AccountBalanceService class which triggers the actual method for authentication.

When you run your tests you will get the following result:

IntroductionToMocking_Image001small.PNG

The test passed and you have a big smile on your face. Not so fast joy boy! Take a look at the time it took to run the test 6.69 seconds. This is too much time to run a single test. Apart from time there are other problems with the test. The test is dependent on the AverageJoeBankService. If the web service is not available then the test will fail. Unit tests should be independent and they should run fast. Let’s make this test faster by introducing mock objects.

Oh wait! We haven’t explained what mock objects mean in the context of unit tests. Mock objects are like real objects but they don’t do anything. We know the definition we just gave you is kind of crazy but you will know what we are talking about in a minute.

Here is the unit test which uses mock objects:

C#
private AccountBalanceService _accountBalanceService;
private MockRepository _mocks;

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

[Test]
        public void should_be_able_to_get_the_balance_successfully() 
        {
            User user = new User();
            user.UserName = "JohnDoe";
            user.Password = "JohnPassword";

            var averageJoeService = _mocks.DynamicMock<IAverageJoeBankService>();

            _accountBalanceService = new AccountBalanceService(averageJoeService);

            using (_mocks.Record())
            {
                SetupResult.For(averageJoeService.Authenticate(null,
                    null)).IgnoreArguments().Return(true); 

            }

            using (_mocks.Playback())
            {
                Assert.AreEqual(100,_accountBalanceService.GetAccountBalanceByUser(user)); 
            }          
        }

First, we created the MockRepository which is part of the Rhino Mocks frameworks. You might say “What the hell is Rhino Mocks?” Rhino mock is a mocking framework which provides you different mocking features and ways to mock your objects. There are several other mocking frameworks which include NMock, NMock2, TypeMock, MoQ.

Anyway, in the unit test above we are creating a mock object using the following code:

C#
var averageJoeService = _mocks.DynamicMock<IAverageJoeBankService>();
_accountBalanceService = new AccountBalanceService(averageJoeService);

After passing the mocked AverageJoeService (not the real service) to the AccountBalanceService we put our expectations.

C#
using (_mocks.Record())
    {
        SetupResult.For(averageJoeService.Authenticate(null,
            null)).IgnoreArguments().Return(true); 

    }

This means that when the averageJoeService.Authenticate method is fired then returns true so I can proceed further. You can also see that we are not concerned about the passed in arguments and that’s why we are using IgnoreArguments.

The next part is the Playback which is the code that will trigger the expectations and produce the desired result. Here is the Playback part:

C#
using (_mocks.Playback())
    {
        Assert.AreEqual(100,_accountBalanceService.GetAccountBalanceByUser(user)); 
    }

Here is the output of the unit test:

IntroductionToMocking_Image002small.PNG

As you can see, now the unit test only takes 1.81 seconds. Not only is the test faster but now it is not dependent on the AverageJoeBankService. This means that even if the web service is down you will be able to run the above test.

Conclusion

In this article we introduced the concepts behind Mocking. Mocking helps to improve unit tests by removing the outside dependencies which results in better, faster, independent unit tests.

We hope you liked the article, happy programming!

NOTE: We have also created a screencast on this subject which you can view using the following link: Screencast: Introduction to Mocking

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
United States United States
My name is Mohammad Azam and I have been developing iOS applications since 2010. I have worked as a lead mobile developer for VALIC, AIG, Schlumberger, Baker Hughes, Blinds.com and The Home Depot. I have also published tons of my own apps to the App Store and even got featured by Apple for my app, Vegetable Tree. I highly recommend that you check out my portfolio. At present I am working as a lead instructor at DigitalCrafts.




I also have a lot of Udemy courses which you can check out at the following link:
Mohammad Azam Udemy Courses

Comments and Discussions

 
QuestionCan you give a detail introduction of Mock? Pin
Neerajan Lamsal22-Apr-11 0:35
Neerajan Lamsal22-Apr-11 0:35 
GeneralThanks you Pin
Marcus Poilus26-May-10 6:29
Marcus Poilus26-May-10 6:29 
QuestionWhere is the source? Pin
MP3Observer26-Oct-08 6:14
MP3Observer26-Oct-08 6:14 
AnswerRe: Where is the source? Pin
azamsharp26-Oct-08 6:44
azamsharp26-Oct-08 6:44 
AnswerRe: Where is the source? Pin
azamsharp28-Oct-08 7:42
azamsharp28-Oct-08 7:42 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.