Posts tagged NUnit
Aqua Bird AutoMocking Magic
0If you use any kind of mocking framework then this post is for you. If you don’t use a mocking framework, then I suggest you read this post anyways; it might make you see the light. In this post, I will show you how to utilize classes written by us here at Aqua Bird Consulting to trim your unit tests. There are some requirements that your code has to meet before you start using these awesome classes. You will see these requirements below. You probably already follow these conventions.
- You will need Moq (a mocking framework) or you may modify the code to use another framework like RhinoMocks.
- All classes that will be tested have to have all dependencies injected through the constructor.
- All mocked objects must abide by the rules of the mocking framework. i.e. The dependency implements a specific interface or methods/properties of an object to be mocked are marked virtual.
These are three simple rules, nothing to it really. Let’s take a look at what the test will look like before and after using these Aqua Bird classes. The example below is for a simple contact controller implemented in an Asp.Net MVC web application; we use NUnit at Aqua Bird Consulting.
Here is the before:
public void ContactController_Contact_Sends_An_Email()
{
// Create Mocks
var contactMock = new Mock<ContactSettings>();
var emailMock = new Mock<IEmailService>();
contactMock.SetupGet(s => s.ToAddress).Returns("test@test.com").Verifiable();
emailMock.Setup(e => e.Send(It.IsAny<MailMessage>())).Returns(true).Verifiable();
// Inject Mocks
var controller = new ContactController(emailMock.Object, contactMock.Object);
var viewResult = controller.Index(new ContactMessage()
{
Name = "Test",
Email = "test@test.com",
Text = "Hey what's up",
Subject = "hey"
}) as ViewResult;
Assert.IsNotNull(viewResult);
Assert.IsInstanceOf<ContactViewModel>(viewResult.ViewData.Model);
Assert.IsNotNull(viewResult.ViewData.Model);
// Verify Each Mock
contactMock.VerifyAll();
emailMock.VerifyAll();
}
Here is the after:
public void ContactController_Contact_Sends_An_Email()
{
var mock = new MockController<ContactController>();
mock.Mock<ContactSettings>().SetupGet(s => s.ToAddress).Returns("test@test.com").Verifiable();
mock.Mock<IEmailService>().Setup(e => e.Send(It.IsAny<MailMessage>())).Returns(true).Verifiable();
var viewResult = mock.Controller.Index( new ContactMessage()
{
Name = "Test",
Email = "test@test.com",
Text = "Hey what's up",
Subject = "hey"
} ) as ViewResult;
Assert.IsNotNull(viewResult);
Assert.IsInstanceOf<ContactViewModel>(viewResult.ViewData.Model);
Assert.IsNotNull(viewResult.ViewData.Model);
mock.VerifyAll();
}
You can see that in this one particular example we shaved four lines down to two. For a simple class it doesn’t seem very helpful, but with more complex classes that take several dependencies it can save a lot of time and typing. The thing you might have noticed in the example contact controller example is that we mocked both an interface and an object. So how does this all work?
Let me first start by explaining what the automocking class does on a high level.
- When you initialize a new automock class we first look at the constructor, and retrieve the most complex one (most parameters).
- we then get all parameters to this constructor and we begin to create the mocks
- As we create the mocks we place them into a dictionary
- After all the mocks are created, we create the instance of the class to be tested
- Let the testing begin!!!
/// <summary>
/// Will create the mocks and inject a newly created object of type T
/// only supports constructor based injection
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class MockObject<T>
{
/// <summary>
/// Dictionary that holds all the mocks
/// </summary>
private readonly Dictionary<Type, Mock> _mocks;
/// <summary>
/// Initializes a new instance of the <see cref="MockController<T>"/> class.
/// </summary>
protected MockObject()
{
_mocks = new Dictionary<Type, Mock>();
InitializeMocksAndObject();
}
/// <summary>
/// Gets the controller.
/// </summary>
/// <value>The controller.</value>
protected T Target { get; set; }
/// <summary>
/// Initializes the mock dictionary and controller.
/// </summary>
protected void InitializeMocksAndObject()
{
Type controllerType = typeof (T);
ParameterInfo[] parameterInfo = null;
ConstructorInfo constructor = null;
// Go through the constructors and find the most
// complex one, if things are right (one constructor)
// then this should go through once
foreach (ConstructorInfo c in controllerType.GetConstructors())
{
ParameterInfo[] temp = c.GetParameters();
if (parameterInfo != null && temp.Count() <= parameterInfo.Count())
continue;
constructor = c;
parameterInfo = temp;
}
// Now that we have are most complex constructor
// we know what types we need to call
if (parameterInfo != null)
foreach (ParameterInfo info in parameterInfo)
{
// Have to call register type through reflection
// just the nature of the beast
MethodInfo method = typeof (MockObject<T>).GetMethod("RegisterType",
BindingFlags.Instance | BindingFlags.NonPublic);
MethodInfo generic = method.MakeGenericMethod(info.ParameterType);
generic.Invoke(this, null);
}
// Create The Controller
var parameters = new List<object>();
foreach (Mock mock in _mocks.Values.ToArray())
parameters.Add(mock.Object);
Target = constructor != null ? (T)constructor.Invoke(parameters.ToArray()) : default(T);
}
/// <summary>
/// Mocks this instance.
/// </summary>
/// <typeparam name="TMockType">The type of the mock type.</typeparam>
/// <returns></returns>
public Mock<TMockType> Mock<TMockType>()
where TMockType : class
{
return _mocks[typeof (TMockType)] as Mock<TMockType>;
}
/// <summary>
/// Registers the type.
/// </summary>
/// <typeparam name="TMockType">The type of the mock type.</typeparam>
protected void RegisterType<TMockType>()
where TMockType : class
{
var mock = new Mock<TMockType>();
_mocks.Add(typeof (TMockType), mock);
}
public void VerifyAll()
{
foreach (var mock in _mocks)
mock.Value.VerifyAll();
}
}
There it is. This is the abstract base class that performs the majority of the work, mocking up objects and placing them in a dictionary. In the example with the contact controller, I inherited from the MockObject base class and created a sub class with a property called “Controller” so that my tests read better. You can follow this convention to create more readable tests.
/// <summary>
/// Using the Moq Framework this will create all
/// the mocks and the controller (only supports constructor based DI)
/// </summary>
/// <typeparam name="T"></typeparam>
public class MockController<T> : MockObject<T>
where T : IController
{
public T Controller
{
get { return Target; }
}
}
So there you have it, if you would like to run an example of the automocking class, I have included a sample project below with all the files and dependencies you’ll need to get started. Feel free to modify the code and make any changes you feel necessary.
Thanks,
Khalid Abuhakmeh
