So to start with, most important Concept, that is misunderstood as an unnecessary task by most of the developers – Unit Testing!!!
First, let us understand why it is very necessary for a developer to write unit test cases?
Deployment:
- The most basic reason why test cases are written is, when we work in a team, many developers are contributing to the code base, and sometimes even on same modules.
In such scenarios, if any developer checks-in a piece of code that breaks the functionality of certain module, unit test cases is the first line of call which alerts us about the failure. - Recommendations:
A unit test case must be written for each line of code, before checking-in the changes.
Even if a defect is fixed, unit test cases must be written, to cover its scenarios.
Security:
- We as developers know exactly how a certain module will work based on how we code it, A tester can test the module but can only imagine it from the user perspective, but in case of malicious attack, the attacker will think like a developer to exploit the vulnerabilities, now if we could at lease write unit test cases to make the data validations perfect with respect to back-end considering all the alpha, beta and gamma scenarios, then we can deliver a far better quality code and the reports of Security Tests also can be improved.
Now let us see the BIG question when I say Unit Test Case, what does it mean
Unit – In layman’s terms a Unit is an independent block of code, if it has any dependencies from outside world, those must me MOCKED!!!
MOCKED… now comes the efficiently build framework into the picture, MOQ Framework
Mocking a dependency means mocking the result of a function, it may be an output parameter, a reference parameter or as basic and the return value.
The Mock or MOQ framework is used to achieve this.
MOQ framework can be easily installed using NuGet Package Manager.
Let us consider a class
class UserAdmin{
private readonly IUserService _userService;
UserAdmin(IUserService userService){
_userService = userService;
}
public bool IsUserAdmin(int UserId)
{
return isRoleCorrect(“Admin”,_userServices.InRole(UserId))
}
private bool isRoleCorrect(string Required, string UserRole){
return Required.Equals(UserRole);
}
}
Above UserAdmin class, has a dependency on UserService,
let us redefine this class based on our understanding of Unit.
So when we look at a public function, it is a Unit, it can have dependencies inside the class, like private function isRoleCorrect,
but if we see closely it also has a dependencies on UserServices, which comes outside our scope, because it may be getting data by querying a database server or some other service, in case the Database is down or the service is down, our test case will fail, but that defies the main purpose of Unit Test Case, If we try to test the database, we are doing an integration test, now what is integration test, that maybe whole together a new topic for a different blog ;) but just a brief, it tests if all the components of application are working in sync.
Coming back to the point, in this case, we need to mock this External Service.
Now let us take a look at the code for the test case.
[TestClass]
Class TestUserAdmin{
Mock<IUserService> mockUserService;
UserAdmin userAdmin;
[TestInitialize]
public void init(){
mockUserService = new Mock<IUserService>();
userAdmin = new UserAdmin(mockUserService.Object)
}
[TestMethod]
public void TestIsUserAdmin(){
mockUserService.Setup(x=>x.InRole (It.Any<int>())).Returns(()=>”Admin”);
var result = userAdmin. IsUserAdmin(1);
Assert.IsTrue(result);
}
}
Starting with some of the basic concepts, like Test Class Attributes,
[TestClass] – It sets a class as a Test Class, basically notifying Test Explorer, this class has Some Sort of tests, maybe Unit Tests or integration tests
[TestInitialize] – The function assigned to this attribute, runs before every test case runs, will be bringing up a good coding technique using this function later while explaining the test case.
[TestMethod] – This notifies the Test Explorer that this is a Test Case.
There is one more attribute, that I didn’t use in my above code, [TestCleanup], now this is used rarely, basically, this runs after every test case, so for analogy, we can consider [TestInitialize] as the Constructor and [TestCleanup] as the destructor of the [TestClass].
Coming back to MOQ framework,
The MOQ framework’s Mock class needs to be initialized by DataType of the service,
hence,
Mock<IUserService> mockUserService = new Mock<IUserService>();
this gives access to all the public Properties and Methods to the object and we can now mock or set up their values.
Now, most of the applications are designed using Dependency Injection, where we use a Framework like Ninject and inject the dependencies using a Container or a Register.
Now comes the importance of [TestInitialize]
Let us consider a scenario where the application is under development and developers keep adding new dependencies to the class via the constructor, so if we initialize the class once in every test case, every time we add a dependency, we need to modify all the call of initializing the class
In our example, it is just once, but if you consider an application with thousands of test cases, it makes a lot of difference.
Again coming back to MOQ,
So once the Mock Class is initialized by Interface of the dependence, we use functions like Setup(), SetupSet(), SetupProperty() etc to set the return value of a method or to set a property.
Hence,
mockUserService.Setup(x=>x.InRole (It.Any
now in our case, we need to set a return value to InRole and we also need to pass an int value to the function.
What we are writing here is actually creating a signature, which needs to be matched during runtime,
we could have also written the code as
mockUserService.Setup(x=>x.InRole (5)).Returns(()=>”Admin”);
even this will create a signature, but this will only mock value if the function call is made with parameter value 5,
this works very well but, it binds us to use only specific values.
Using It.Any<DataType>(), makes a signature which is applicable to any parameter of “DataType”.
And .Return(()=>”Admin”) statement returns the value “Admin” when the function is called matches the signature.
In case a function is called multiple times within the same block, and we need to return different values each time the function is called, we can use SetupSequence() and use multiple Return statements.
mockUserService.SetupSequence (x=>x.InRole (It.Any<int>()))
.Returns(()=>”Admin”)
.Returns(()=>”User”);
Now if you debug the code line by line, you will see the control going through private function isRoleCorrect, its a bit confusing at first look but if you try to test or mock private methods, you are breaking encapsulation. So we should look at private method as part of the method we are testing.
Finally, the most important part of the test case, validating the results.
Hence,
Assert.IsTrue(result);
Assert class is used to verify the output of the function, it has different functions, like IsTrue, IsFalse, IsNull etc.
At times we also need to test functions that do not return anything, this is were Assert Class fails, but MOQ has a feature to verify if the function was called.
Once the class is mocked, using MOQ, the mocked class is monitored by the framework, to achieve this verification we can use,
mockUserService.Verify(x => x.InRole(It.Any<int>()), Times.AtLeastOnce());
this piece of code will test if the function InRole() was called at least once during the execution of the code.
The test case above is written, considering the output or the return value will be coming out to be true, hence we are testing the result for true.
Lastly, a quick technique to mock protected classes is to create a new class and inherit the protected class over it.
Class A{
public int Amount { get; set; }
public bool Paid { get; set; }
protected A(int amount, bool paid){
Amount = amount;
Paid = paid;
}}
Now consider a function which return A,
public A InRole(int UserId)
mockUserService.Setup(x=>x.InRole (It.Any<int>())).Returns(()=>new A{ Amount = 5, Paid = true});
The object of class A cannot be returned as the constructor of the class is protected, and the above piece of code will result into a compilation error.
To overcome this we can simply create a class lets suppose MockA and inherit A to it,
MockA : A{
// In this class, I will have access to members of class A.
}
hence, now I can go ahead and return the object of class MockA and since the parent of MockA is A, it can be accepted in all functions that need the parameter of class A.