Are you looking for a solution to your unit tests modifying data? Perhaps your unit tests are so slow that none of your teammates bother running them? You need mock objects.
The following items will be covered to help you write better tests:
- Why Mocking – how mock objects help you
- Real World Example –an example of code to be tested
- Testing the Example –how to use mocking to test the example
- AAA Pattern – a pattern emerges when writing clean tests
Mocking is one of the most important factors in writing better unit tests. It drastically minimizes a test’s execution time and gives you an upper hand in validating complex logic without disk, database or service dependencies.
Mocks are more than the default-valued objects known as stubs. Mocks act as collaborators and are subject to behavioral modification. These collaborators will help you achieve your desired unit-testing goal for a given system and a controlled set of inputs. This is achieved by having the mock object stand in for the real object and returning data you have specified.
To get a complete overview of mocks, an informative article named “Mocks aren’t stubs” by Martin Fowler is a must read.
After you are finished, it’s time to give you a good grasp of mocking with a real world example.
Real World Example
I am going to implement part of a banking system. This includes the transfer of funds between two different currency accounts using the currency converter service.
To begin, I have created an ICurrencyService interface:
This service interface will be injected to an AccountsService class that is responsible for the transfer funds operation. Once the source and destination account objects are passed to the operation, it will then withdraw from source, convert the currency based on current rate, and finally deposit the converted amount to the target account. There will be a check for available balance, authorization, approval, etc. in more complex scenarios, but they are out of scope for this article.
AccountService : IAccountService
.currencyService = currencyService;
TransferFunds(Account from, Account to,
conversionRate = currencyService.GetConversionRate(from.Currency, to.Currency);
convertedAmount = amount * conversionRate;
Testing the Example
The goal is to validate or assert the transfer funds operation between two accounts. Therefore, this is the system under test (SUT), and the currency service is the collaborator which will be mocked. I am using JustMock for this purpose, but the core concept is the same with other mocking tools.
First I will create the mock of the ICurrenyService interface:
ICurrencyService currencyService = Mock.Create<ICurrencyService>();
From the account service implementation, I can see that GetCurrencyService is being called to retrieve the conversation rate. The next step is to set an expected return value for it.
Mock.Arrange(() => currencyService.GetConversionRate(
Mock.Arrange is the entry-point for setting expected behavior for a given mock. This line is self-explanatory, but I did use one extra option: MustBeCalled. This ensures that if currencyService.GetConversationRate is not called with the above criteria, then it will fail the test.
Since I have finished setting the behavior, I will then create an instance of the AccountService class followed by the source and destination Account classes.
var accountService =
var canadianAccount =
var britishAccount =
Next, I will add some money into the GBP account:
Then transfer it to my Canadian account:
accountService.TransferFunds(britishAccount, canadianAccount, 100);
Once the transfer is complete, I need to make sure the operations happened as expected. I will first assert the balance of the two accounts:
Then I will assert the mock to verify whether the required GetConversationRate method is called as expected:
You may have noticed that there were three easy steps involved with the unit test. This is part of a well-known pattern called Arrange – Act – Assert or AAA. JustMock’s syntax is implemented to strictly follow the AAA pattern to give you a well-structured flow, even in the most complex scenarios.
In this post, I described how mocking will help you. I then built an example project and test to illustrate how to proceed. Mocking helps you write clean unit tests, and it enables you to focus on the test logic by isolating external factors. With mocking, unit testing is no longer a chore.