Wooden mechanical horse mock during World war one
Copyright Crown
Introduction
Pre-requisite
In case you have never done unit testing, probably this article will be Chinese for you and if you are already Chinese then it will be French :). You would probably like to read my Unit testing article first and then move ahead.
The world of partial testing
Everybody bumps with partial testing now or then. And well everybody has their own way of achieving it. Let me quickly recap what I mean by “partial testing”, first for people who are new to it, or rather I will say they have come across it and we just need to relate it.
“First thing, this word “Partial testing” is not an official vocabulary; at least I am not aware of it. I personally feel comfortable using it. So excuse me if I have overstepped in any way.”
Now let's say you have a nice data access layer component which does CRUD (Create, Read, Update, and Delete) on your database. When each of these operations is performed by the data access layer it needs to send an email about the activity. In simple words the database component is dependent on the send email component.
Now let’s visualize a scenario. Let’s say you want to Unit Test the database component and the send email component is not ready or the SMTP configuration is not available. So if you hit your test cases on the database component you will get a FATAL error which does not help out.
In case you are new to unit testing start here: VSTS UNIT Testing.
In simple words you want to only test “Database component” and “simulate” the “Send email” component for now. Summing up, you want to partially test some part of your system and “simulate” the other part of your system which is half done.
Six places where partial testing is evident
Need of partial testing comes in different forms. Below are six scenarios where partial testing is really helpful.
Non-available / complex environment: We all know all code needs an environment. Sometimes these environments are not available / not completed / not configured when you do testing, but we still want to test the rest of the code which is completed. For instance in the previous introduction we wanted to test the database code but the SMTP configurations were not available.
Another classic example is if you want to test ASP.NET behind code, it needs an HTTP context object, request object, and response object. These objects are created when you have a full-fledged web server like IIS. When we do unit testing there is no way we can create these objects in a simple way.
Regression testing: The second place where partial testing is very much needed is “maintenance”. Maintenance is an important part of the software development life cycle. One of the important activities of maintenance is “change request”. When these change requests are applied they only change certain parts of the code. Logically you would like to only test those changed code and the impacted areas where this code is consumed. In other words you would like to do “Regression testing”.
For instance you can see we have an invoicing and accounting application which is under maintenance and now let’s say we apply some change requests in the product class (invoicing section). In this case we would like to only run test cases of the product class and the impacted areas around it. But we would avoid running the accounting test cases. Because the accounting section was not impacted at all.
So again here we would like to implement partial testing, i.e., we just “simulate” all the classes from the accounting component and only run the product test cases and impacted invoicing test cases.
Test driven development: We are not big fans of TDD (no offense meant) but this is again one area where partial testing is much needed. In case you are new to TDD watch this video on TDD (Test Driven Development).
| In TDD we first start with a test case rather than the actual code.
So we write the test case, we write enough code by which test cases pass, we add some more functionality, we test, we again add some more functionality, again test, and this continues until the logic is completed.
Now in this scenario, again at a given moment of time you will have half-done code but you still want to test the complete code. Again a situation which very much calls for partial testing.
|
Minimize testing time: Nowadays people want testing to be faster and efficient. Many times the test cases are optimized, but the business system takes their own sweet time for execution.
For example you have a component which calls some other component “synchronously”. For now assume that the other component is a long running task.
Now if you want to test this component, you have to also run your long running task. As the component calls the same synchronously, the test case will take a long time to execute. So if somehow you can only test the component and “simulate” the long running task, your test case can complete faster.
Development dependency: You are working / testing on a code and that code needs some other component or a third-party code. This other component is half ready or not ready at all. So you would like to do partial testing on your completed code and “Simulate” the dependent code.
Workflow testing: One of the indirect benefits of “Simulation” testing is behavioral testing. In simulation testing, technically, we get a full control over the methods. With this full control we get to know if the method has executed or not. So if you want to test correctness of sequence of workflows or how many number of times the method has been called etc.,“Simulation” testing helps.
Simulate/Fakes/ Mocks – Same goals
Frankly English is our second language, so sometimes we use our own vocabulary which makes us comfortable. But due to cultural differences (Sukesh and I stay in Asia) the other parts of the earth can mistake us saying something else.
In the previous section we emphasized on the importance of partial testing; now that’s one side of the coin. To achieve partial testing we also said we need to “Simulate” the other part of the code which is not available.
For various reasons “Mock” is a more official word which is used rather than “Simulate”. So hence forth I would like to swim with the tide and we will call “Simulation” as “MOCK”.
VS 2012 has implemented partial testing by using “Fakes”, http://msdn.microsoft.com/en-us/library/hh549175.aspx. So one more vocabulary to add to the chaos.
But whatever term you use, the goal is the same. So we would term partial testing as “Mock” testing henceforth in the article to maintain consistency with the widely accepted vocabulary.
Quick note: The MOQ testing team has chosen the word Mock because it’s a more widely accepted terminology, read here for more details. Below is a simple word from the MOQ team.
“But I also think the generic concept of a ‘mock’ in the general sense is used much more extensively than ‘stub’ or even ‘fake’” - Mr. Daniel Cazzulino MOQ testing team.
First thing first, let’s get a good MOCK tool
Now the good news is that we have lots and lots of tools for “Mock” testing, including the one introduced in VS 2012, Fakes. But to keep this article short and sweet we will be choosing two of them: MOQ(open source) and JustMock (paid). In a future article I will talk some restrictions on the open MOQ which compelled us to talk about the paid mock tool JustMock.
You can download MOQ from http://code.google.com/p/moq/ and JustMock from http://www.telerik.com/products/mocking.aspx
Thanks Mr. William Wake for the AAA style
Before we start Mock coding with any of the tools above, let’s get into a standard structure of writing unit test cases, i.e., AAA style. Almost all mock testing tools follow this structure. This will make our test look neat, tidy, and readable.
Now all unit test cases can be visualized into three larger sections: Arrange, Act, and Assert.
Arrange: Make the setup ready for test cases.
Mathsobj = new Maths();
Act: Execute the test case
int total = obj.Add(10,10);
Assert: Check is the test case passed.
Assert.AreEqual(20,Total);
Sample code for Mock testing
Let’s create a simple sample code for MOQ testing first and then we will do one code for “JustMock”. Here’s what we will do. We have a simple Customer business class as shown in the below code. This class has a simple function called SaveRecord
. This function saves the customer data to the database.
Before the customer data is saved to the database it sends an email using the SendEmail
function. Let’s assume for now the SendEmail
is not configured because we do not have the SMTP details in place. So we would like to Mock the SendEmail
function and test the SaveRecord
function.
public class ClsCustomerBAL
{
public virtual bool SendEmail()
{
....
....
}
public bool SaveRecord(string strCustomerName)
{
this.SendEmail();
using(SqlConnection objConnection = new SqlConnection(ClsCustomerBAL.ConnectionString))
{
SqlCommand objSelectCommand = objConnection.CreateCommand();
objSelectCommand.CommandText = "Insert Into TblCustomer(CustomerName) values(@CustomerName)";
objSelectCommand.Parameters.AddWithValue("@CustomerName", strCustomerName.Trim());
objConnection.Open();
objSelectCommand.ExecuteNonQuery();
}
return true;
}
}
Using MOQ and JustMock
Below is the code for “MOQ” and “JustMock” in the AAA style for the above described ClsCustomerBAL
class. The code for Act and Assert is pretty plain and self-understanding. Now only that needs explanation is the Arrange section.
| MOQ | JustMock |
Arrange |
Mock<ClsCustomerBAL> target = new
Mock<ClsCustomerBAL>();
target.Setup(x => x.SendEmail()).Returns(true);
|
ClsCustomerBAL target = new ClsCustomerBAL();
bool called = true;
target.Arrange(() =>
target.SendEmail()).DoInstead(()=> called = true);
|
Act |
string strCustomerName = "MOQ Test Data";
bool returnvalue =
target.Object.SaveRecord(strCustomerName);
|
string strCustomerName ="Just Mock Test Data";
bool returnvalue = target.SaveRecord(strCustomerName);
|
Assert |
Assert.AreEqual(true,returnvalue);
|
Assert.AreEqual(true, returnvalue);
|
Understanding the Arrange section
Let’s first cover MOQ. The first step we need to create is the Mock instance using Mock
. Below is the code for MOQ.
Mock<ClsCustomerBAL> target = new Mock<ClsCustomerBAL>();
For just mock you can create a simple object or you can use Mock.Create
as well.
ClsCustomerBAL target = new ClsCustomerBAL>();
or
ClsCustomerBAL target = Mock.Create<ClsCustomerBAL>();
Once the Mock
object is created, we need to specify how the SendEmail
function should be mocked. Below is the MOQ code which specifies that the SendEmail
function should just return true
and avoid running the actual logic.
target.Setup(x => x.SendEmail()).Returns(true);
Below is a simple code of how the SendEmail
function is mocked. You can see the word Arrange which is very much in line with the thought of “AAA”. In JustMock
we have the DoInstead
function which takes a delegate as input and defines what should be the output.
bool called = true;
Mock.Arrange(() => target.SendEmail()).DoInstead(()=> called = true);
Video on MOQ
Visuals are visuals. Below is a simple video which demonstrates a simple sample of MOQ.
To Mock private or not?
If you watch the previous example closely you can see that SendEmail
function is public
and virtual
. Now as a developer you would like to follow OOP principles and make the SendEmail
method as private rather than exposing it publicly. If you compile, you hit an error with MOQ as shown below:
public class ClsCustomerBAL
{
public virtual bool SendEmail()
{
}
}
public bool SaveRecord(string strCustomerName)
{
this.SendEmail();
}
In simple words MOQ does not allow mocking of “private” methods. The reason given is as follows.
“Testing private methods is a bad taste for Mock purist testers. From a mock testing perspective we just test the public API which is one logical closed unit. What happens internally is a black box and isolating or mocking those sections is not logical. But if you think those individual methods should be tested separately then probably they deserve a separate class.”
This argument sounds completely logical. We are concerned only about the public API which gives us the output and that’s what we should be testing as one logical unit.
But I still personally feel mocking private methods is still worth when you are looking at minimizing testing time or simulating complex environments. So if some of your private methods are taking too much time probably mocking is a good idea.
As MOQ has limitations or I will say it’s more of by design, we can use JustMock for the same. Below is a simple sample code with AAA style.
Section | Code |
Arrange |
Customerobj = new Customer();
bool called = false;
Mock.NonPublic.Arrange(obj, "Validate").DoInstead(() => called = true);
|
Act |
obj.Add();
|
Assert |
Assert.IsTrue(called);
|
The Validate
method is a private method in the customer class. By using the NonPublic
function we can mock Validate
to return true.
Mock.NonPublic.Arrange(obj, "Validate").DoInstead(() => called = true);
By product of Mock testing: Behavior verification
Now that we can intercept calls to a “method” we can also achieve a nice byproduct called as “Behavior verification”. In our above code which was under test, let’s say we want to ensure that the email is first sent and the customer is later inserted in to database. In simple words we want to test the sequence of calls of these methods.
Below is a simple code to test behavior testing using MOQ.
So first create the mock object.
int order=0;
Mock<clscustomerbal> target = new Mock<clscustomerbal>();
Attach a callback with an increment on a counter which will check the sequence of how methods are fired. For example you can see in the below code the SendEmail
increments order counter and checks the value. In the same way we have done for SaveRecord
. For send email the order counter value should be zero and for save record it will be 1.
target.Setup(d => d.SendEmail()).Callback(() => Assert.AreEqual(order++, 0));
target.Setup(d => d.SaveRecord()).Callback(() => Assert.AreEqual(order++, 1));
target.Object.SaveAll();
Below goes the code for JustMock:
ClsCustomerBAL target = new ClsCustomerBAL();
Mock.Arrange(() => target.SendEmail()).DoInstead(() =>
{
Assert.AreEqual(1, counter++);
});
Mock.Arrange(() => target.InsertCustomer(Arg.IsAny<string>())).DoInstead(() =>
{
Assert.AreEqual(2, counter++);
});
Source code downloads
You can download the complete source for the article from here.
Thanks Mr. Sukesh
All the above code and inputs were given by Sukesh:http://www.sukesh-marla.com/. Without him I would be slogging for nights figuring out things.
For further reading do watch the below interview preparation videos and step by step video series.