In this article we will understand
various mocking setup using Moq framework. Basically those setup will help in time of
unit testing in application.
If you are bit experience in
unit testing then probably you are aware from those concepts, we know that
mocking is one operation where we mimic the original operation with our custom
or fake operation. In time of
application development, we now and then see that one component is dependent on
another component and we cannot wait till the completion of dependent object.
In this situation, concept of
mocking comes into picture. The mock object will mimic the original object, so
that we can carry one the development process.
There are many mocking
frameworks in market which we can use in time of mock object creation. Moq is
one of them. It is free and simple to use. In this article we will use Moq as
mocking framework. In time of mock setup there might be different situation
which need to implement in time unit test configuration. In this example we
will understand few important setup of Moq framework.
At first, give the reference of
Moq framework to your application. Once you give the reference, it will show in
reference folder of solution, just like below.
So, let’s start with the first
configuration.
Returns statement to return value
We can setup the expected return
value to a function. In this example we will setup Hello() function using mock
object and then we will setup , after execution of Hello() function it will
return “true” always. Here, true is primitive type value, in need we can return
our custom complex type too. Please notice that we have declared Hello() function
as virtual, because Moq demands that . The function should defined as virtual
when we are going to mock a concrete implementation. Have a look on below code.
namespace TestMVC
{
public class TestClass
{
public virtual Boolean Hello()
{
throw new Exception();
}
}
[TestClass]
public class MVCUnitTest
{
[TestMethod]
public void MockAlways()
{
var mock = new Mock<TestClass>();
mock.Setup(x => x.Hello()).Returns(true);
Assert.AreEqual(mock.Object.Hello(),
true);
}
}
}
Perform certain task
after execution of certain function
This is another very important setup, sometime it’s needed
to perform certain operation after completion of some operation or after
execution of some function. For example, we want to count the number of times
of a function execution and depending on times we will make decisions. In this situation we can setup callback() in
time of mock. Here is sample example.
[TestClass]
public class MVCUnitTest
{
[TestMethod]
public void MockAlways()
{
string status = "";
var mock = new Mock<Service>();
mock.Setup(x => x.CallService()).Returns(true).Callback(() => {
//Do some other stuff
status = "FunctionCalled";
});
var consumer = new ServiceConsumer(mock.Object);
Assert.AreEqual(consumer.Execute(),
true);
if (status == "FunctionCalled")
{
//perform other task when finish the first
}
}
}
Once it complete the execution of
CallService() function, immediately it will execute callback and perform
some other operation, In this example just we are setting some variable value
and it might check farther to take decisions in other steps.
Return
multiple values sequentially from mocked function
This is another important setup where the mocked function (I mean the
function setup associated with mock object) will return different value per
each call. Here is simple implementation.
using System;
using ConsoleApp;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using ConsoleApp;
using System.Collections.Generic;
namespace TestMVC
{
public class TestClass
{
public virtual Boolean ReturnSequence()
{
throw new Exception();
}
}
[TestClass]
public class MVCUnitTest
{
[TestMethod]
public void MockAlways()
{
var mock = new Mock<TestClass>();
//First Return True then false
mock.SetupSequence(x => x.ReturnSequence())
.Returns(true)
.Returns(false);
Assert.AreEqual(mock.Object.ReturnSequence(),
true);
Assert.AreEqual(mock.Object.ReturnSequence(),
false);
}
}
}
In this
example we have used multiple Returns() statements and at the first time it
will return true and in next time it will return false. Here is output and we
are seeing that the test is getting pass , as we expected in Assert.
Throws exception in second time
There might
be certain situation where we want such a configuration when at the first time,
the mocked function will return a value but in call of second time it will
throw exception. In this example the function
will return true at first time and in second call it will throw exception.
namespace TestMVC
{
public class TestClass
{
public virtual Boolean Function()
{
throw new Exception();
}
}
[TestClass]
public class MVCUnitTest
{
[TestMethod]
public void MockAlways()
{
var mock = new Mock<TestClass>();
//First Return True then Throws exception
mock.SetupSequence(x => x.Function())
.Returns(true)
.Throws(new Exception());
Assert.AreEqual(mock.Object.Function(),
true);
Assert.AreEqual(mock.Object.Function(),
true);
}
}
}
We are seeing
that it is throwing exception in second call.
CallBase() to call original
implementation
This setup is
helpful when we want to call the original function rather than mocked function.
In this example , Function() is not mocked, just we are calling the original
function with the help of CallBase(). As we throwing exception from Function()
intentionally , the test should throw exception.
namespace TestMVC
{
public class TestClass
{
public virtual Boolean Function()
{
throw new Exception();
}
}
[TestClass]
public class MVCUnitTest
{
[TestMethod]
public void MockAlways()
{
var mock = new Mock<TestClass>();
mock.CallBase = true;
mock.SetupSequence(x => x.Function()).CallBase();
Assert.AreEqual(mock.Object.Function(),
true);
}
}
}
And it’s
throwing exception from Function().
Mock Generic class
The mocking
mechanism of generic class is just like the normal class mocking, have a look
on below example.
public class Hello
{
}
public class TestClass <T> where T : class
{
public virtual Boolean Function()
{
throw new Exception();
}
}
[TestClass]
public class MVCUnitTest
{
[TestMethod]
public void MockAlways()
{
var mock = new Mock<TestClass<Hello>>();
mock.SetupSequence(x => x.Function()).Returns(true);
Assert.AreEqual(mock.Object.Function(),
true);
}
}
Border line:
In this
article we have learned few important mock setups using Moq framework. In my
next article I am planning to explore mock in depth.
No comments:
Post a Comment