In this article, you will learn how to write the test method name, guideline for the naming convention, body structure inside the test method, and why you need object mocking in the test method for unit testing.
Unit Testing
Naming Convention Of Test Method
Traditional Principle Of Unit Test
One Test Method is written to test one and only one method; one Assert
method should test only one expectation at a time.
In short, the principle says – “one function/method and one assert per test method”
So, let’s consider the below example:
Comparing Traditional Principle to the Real World
Test Scenario
Verify the “GetSum
” Method.
Test Cases
Positive Test Cases
TC1
: Given positive values, should return expected result Test Data-1
: firstValue =5
, secondValue =6
Negative Test Cases
TC2
: Given zero values, should produce invalid argument message Test Data-2
: firstValue =0
, secondValue =0
TC3
: Given negative values, should produce invalid argument message Test Data-3
: firstValue =-5
, secondValue =-6
Exceptional Test Cases
TC4
: Given threshold limit values, should throw exception message Test Data-4
: firstValue =2147483647
, secondValue =2147483647
Test Method Example
Now according to the traditional principle, let’s write the test method for the “GetSum
”.
Now according to the traditional principle, we have covered the Positive Test Case with “Test Data-1
”. But what about negative and exceptional test cases??
How do we cover the negative and exceptional test cases with traditional principle??
Behavior Driven Development (BDD)
Why Do We Need BDD
If we want to cover all of the behaviors of our test cases according to our previous example, then we need to follow some technique; so that, we can write down all of the behaviors of the method. So, the BDD which is the technique, gives us the opportunity to fulfill all of the test cases with standard and readable naming convention. Many people, many minds. There are many techniques to write the naming convention of the test method. But it really depends on only you and your preference. There is nothing right or wrong - if you follow some other different technique. Anyway, in short, we can say that - in BDD, components test their expected behavior.
Concept Of BDD
- Given I am a beginner to the BDD technique, and I have never used this technique before
- When I read this tutorial for BDD
- Then I have started to like it and finally I learnt it
BDD Naming Convention
Test Scenario - Verify the “GetSum
” Method
Test Cases - Positive Test Cases
TC1
: Given positive values, should return expected result Test Data-1
: firstValue =5
, secondValue =6
Test Method - Naming Convention
GivenPositiveVaidValuesAsParams_WhenGetSumIsCalled_ThenItShouldReturnSumValue
More Readable
Given_Positive_Vaid_Values_As_Params_When_GetSum_Is_Called_Then_It_Should_Return_Sum_Value
Negative Test Cases
TC2
: Given zero values, should produce invalid argument message Test Data-2
: firstValue =0
, secondValue =0
Test Method - Naming Convention
GivenZeroValuesAsParams_WhenGetSumIsCalled_ThenItShouldThrowInvalidArgumentException
More Readable
Given_Zero_Values_As_Params_When_GetSum_IsCalled_Then_It_Should_Throw_Invalid_Argument_Exception
TC3
: Given negative values, should produce invalid argument message Test Data-3
: firstValue =-5
, secondValue =-6
Test Method - Naming Convention
GivenNegativeValues_WhenGetSumIsCalled_ThenItShouldThrowInvalidArgumentException
More Readable
Given_Negative_Values_When_GetSum_Is_Called_Then_It_Should_Throw_Invalid_Argument_Exception
Exceptional Test Cases
TC4
: Given threshold limit values, should throw exception message Test Data-4
: firstValue =2147483647
, secondValue =2147483647
GivenMaxLimitValuesOfIntAsParams_WhenGetSumIsCalled_ThenItShouldThrowSumException
More Readable
Given_Max_Limit_Values_Of_Int_As_Params_When_GetSum_IsCalled_Then_It_Should_Throw_Sum_Exception
Body Structure Of Test Method
There are no hard code rules for that. We generally follow the AAA structure because it’s easy to read and understand. The general AAA structure is given below for the Test
method.
AAA - Structure
- Arrange
- Act
- Assert
Arrange
In this Arrange portion, we declare variables and create the instance of the objects of the classes.
Act
The verified method is called in the portion. This is mainly used for passing the input parameters into the method and collecting the actual return result from the calling method.
Assert
In this portion, we compare the actual output result of the calling method with the expected output result. The test is passed or failed depending on this Assert
portion.
Object Mocking For Unit Testing
Why Do We Need Mock
Suppose you need to test the behavior of one method and it has an external service or method within it. During the unit testing, we have to avoid these kind of external dependencies and the mock technique gives us the facility to avoid the behavioral test of the external method or service.
Why?? Because, according to the first principle, we all know that - "Test the logic of the class only, nothing else” Unit test NEVER uses - configuration settings, a database, logging, another application/service/file/network I/O.
Anyway, let’s see the example:
This GetSum
method has no external dependencies within it. So, it does not need object mocking.
Now, see the below example of the class and it has two dependencies and these are CheckingAccount
and SavingAccount
.
Now, we want to verify the method “GetTotalMoneyByUserAccount
” and it has two dependencies within it. So, to solve this kind of situation, we need object mocking.
Mock Framework
There are many object mock framework like Typemock Isolator, Rhino Mocks, Moq and NMock. You can use any one of them.
Requirement before Making Mock
- The class can’t be sealed.
- The method can’t be
static
; but if you need then use Adapter pattern. - You can mock if Interfaces, Abstract methods or properties or Virtual Methods or properties on concrete classes.
Adding MOQ For Unit Testing Project
Select your Unit Testing Project. Go to Reference> Click right button of the mouse and select “Manage NuGet Packages”. Now write down ‘Moq
’ into the search textbox and finally install it to your project.
Object Mocking Using MOQ
In the above example, look at the line number 35 and 41; here first, we are creating instances of the object using Moq
.
Mock<IBankAccount> mockCheckingAccount = new Mock<IBankAccount>();
Mock<IBankAccount> mockSavingAccount = new Mock<IBankAccount>();
In the line numbers 38 and 44, we are implementing a dummy implementation and if the "GetMoneyByUserAccountNo
" method is called, then it will return the 5 and 6. So, we don't need to know any internal logics of that.
mockCheckingAccount.Setup(a => a.GetMoneyByUserAccountNo(userAccountNumber)).Returns(5);
mockSavingAccount.Setup(a => a.GetMoneyByUserAccountNo(userAccountNumber)).Returns(6);
Now in line number 48 which shows that we are injecting the mock objects into the class via constructor.
SimpleMath simpleMath = new SimpleMath
(mockCheckingAccount.Object, mockSavingAccount.Object);
Secondly, in the line number 56 of the 'Act' portion, we are calling the verified method and the output result goes into the actualSumResult
variable and finally in line number 59, which is giving us the actual output result.
actualSumResult = simpleMath.GetTotalMoneyByUserAccount(userAccountNumber);
My main goal to introduce you to the object mocking world. So, this is just an example. You can use any of the mocking framework.
How to Call Order Of Test Methods using Moq Sequences
Download Moq.Sequences.dll from Github, then add Moq.Sequences.dll as a reference in your .NET project and add a using Moq.Sequences
; in your test class. Or simply use "Manage NuGet Packages” Manager and type "Moq.Sequences
" and search it. Finally, install it to your project and use it to your call as a reference.
Moq.Sequences
supports the following:
- Checks order of the method calls, property gets and property sets
- Allows you to specify the number of times a call is made before the next one is expected
- Allows inter-mixing of sequenced and non-sequenced expectations
- Thread safe – each thread can have its own sequence
Example for Calling Methods Sequentially
[TestMethod]
public void Given_Valid_Data_For_Object_Model_When_TestMethod_
Is_Called_Then_It_Should_Be_Done_Successfully()
{
......
......
using (Sequence.Create())
{
Given_Valid_Template_Data_When_MethodSave_Is_Called_
Then_It_Should_Be_Saved_Successfully();
Given_Valid_Template_Value_When_MethodUpdate_Is_Called_
Then_It_Should_Update_Template();
Given_Valid_Template_ID_When_DeleteTemplate_Is_Called_
Then_It_Should_Delete_Template();
}
......
......
}
[TestMethod]
public void Given_Valid_Data_For_Model_When_TestMethod_
Is_Called_Then_It_Should_Be_Done_Successfully()
{
......
......
using (Sequence.Create())
{
mockObject.Setup(x => x.MethodA()).InSequence();
mockObject.Setup(x=>x.MethodB()).InSequence(Times.AtMostOnce());
mockObject.Setup(x=> x.MethodC()).InSequence(Times.Once());
}
......
......
}
Part -1 "Software Testing - Best Practice and Principles to Write Unit Testing"
History
- 17th April, 2017: Initial version