In this
article we will understand various mocking setups using Moq framework.
Basically those setups help during the of unit testing of an application. If
you have experience in unit testing then you are probably aware of these
concepts. We know that mocking is an operation where we mimic the original
operation with our custom or fake operation. At the time of application
development, we sometimes see that one component is dependent on another
component and we cannot wait until the completion of the dependent object.
In this
situation, the concept of mocking comes into the picture. The mock object will
mimic the original object, so that we can carry on with the development
process. There are many mocking frameworks on the market which we can use for
our mock object creation. Moq is one of them. It is free and simple to use. In
this article we will use Moq as our mocking framework. At the time of the mock
setup there might be different situations which we need to implement during
unit test configuration. In this example we will understand a few of the
important setups of Moq framework.
At first,
give the reference of Moq framework to your application. Once you give the
reference, it will show in the reference folder of the solution, as shown
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 the Hello() function using a mock object and then we will setup so
that after the execution of the Hello() function it will always return "true." Here,
true is a primitive type value. If we are in need we can return our custom
complex type too. Please notice that we have declared the 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 at the 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
operations after the completion of other operations or after the execution of
some function. For example, we want to count the number of times of a function
execution, and will assess those times in order to influence our decisions. In
this situation we can setupcallback() in time of mock. Here is a 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
completes the execution of the CallService() function, it immediately will execute callback and
perform some other operation. In this example just we are setting some variable
value and it might check further 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 values per each call. Here
is a 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. The first time it will return true and the
next time it will return false. Here is the output and we are seeing that the
test is getting passed, as we expected.
Throws exception in second time
There might
be certain situations where we want a configuration when the mocked function
will return a value the first time, but in if called a second time it will
throw an exception. In this example the function will return true at the first
time and in the second call it will throw an 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, we are calling the original function
with the help of CallBase(). As we throw an exception from Function() intentionally, the test should throw an 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 the generic class is just like normal class mocking. Have a look
in the 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 a few important mock setups using the Moq framework. In
my next article I am planning to explore mocking more in depth.
No comments:
Post a Comment