My favorites | Sign in
Project Logo
                
Search
for
Updated Sep 09, 2008 by slava42
Labels: Featured
Automocking  
Instruction on how to automate mocking using AutoMock container

Introduction

Auto mocking allows you to get object of the type you want to test without setting up mocks by hand. All dependencies are mocked automatically (assuming they are interfaces) and injected into the type constructor. If you need to you can set up expected behavior, but you don't have to.

Requirements

You need to reference these assemblies in your test project:

Usage

AutoMock is a mocking factory. You can ask it for the object you want to test, it will generate all dependencies for you through mocks and allow you to verify them when you're done.

You specify default mock behavior (strict or loose) through by creating custom mock factory and passing it to the 'AutoMock' constructor.

Example Classes

public interface IApple
{
	void Fall();
}

public class Apple :IApple
{
	public void Fall()
	{
	}
}

public class Tree
{
	private readonly IApple _apple;

	public Tree(IApple apple)
	{
		_apple = apple;
	}

	public void Grow() {}
	public void DropApple()
	{
		_apple.Fall();
	}
}

Automatic Dependency Injection

Bar constructor takes IApple as parameter. IApple will be mocked automatically and Mock.Object is passed to the constructor.

var factory = new MockFactory(MockBehavior.Loose);
var container = new AutoMockContainer(factory);
var tree = container.Create<Tree>();
tree.Grow();

factory.VerifyAll();

See Resolving Parameters in AutoFac if you need to specify more parameters for the object you need to use activator with AutoMock.Create.

Setting Up Expectations

You can always get the mock and set up expectations.

var factory = new MockFactory(MockBehavior.Loose);
var container = new AutoMockContainer(factory);

container.GetMock< IApple >().Expect( x => x.Fall() ).Verifiable();
var tree = container.Create<Tree>();
tree.DropApple();

factory.VerifyAll();

Providing Your Own Implementation

You can provide an instance of an interface (no mocking will be done) or specify which class to use as default interface implementation (again, no mocking will be done).

var factory = new MockFactory(MockBehavior.Loose);
var container = new AutoMockContainer(factory);

container.Register< IApple >( new Apple() ); // or mock.Register< IApple, Apple >();
var tree = container.Create<Tree>();
tree.DropApple();

factory.VerifyAll();

Verifying All Mocks

Mocks can be verified when you're done. You can also place mocks verification to the test tear down.

Base Test Class with Auto Mocking

To simplify testing even further you can use a base class for all your tests with common methods to set up mocking. I've implemented the class as part of my Netco project. Bellow is the it's current implementation at the time of writing this article.

Assuming you're using xUnit for testing something like this will work:

/// <summary>
/// Base class for all tests.
/// </summary>
/// <remarks>Provides base auto mocking for the tests.</remarks>
/// <seealso href="http://blog.eleutian.com/2007/08/05/UsingTheAutoMockingContainer.aspx"/>
/// <seealso href="http://code.google.com/p/moq-contrib/wiki/Automocking"/>
public abstract class AutoMockingTests : IDisposable
{
	private MockFactory _factory;

	/// <summary>
	/// Initializes a new instance of the <see cref="AutoMockingTests"/> class.
	/// </summary>
	/// <remarks>Defaults to <see cref="MockBehavior.Loose"/>.</remarks>
	protected AutoMockingTests()
	{
		this._factory = new MockFactory( MockBehavior.Loose );
		this.Container = new AutoMockContainer( this._factory );
	}

	/// <summary>
	/// Changes mocks behavior to <see cref="MockBehavior.Strict"/>.
	/// </summary>
	protected void UseStrict()
	{
		this._factory = new MockFactory( MockBehavior.Strict );
		this.Container = new AutoMockContainer( this._factory );
	}

	/// <summary>
	/// Forces factory verification.
	/// </summary>
	/// <remarks>This is called automatically by xUnit.</remarks>
	public virtual void Dispose()
	{
		if( this.VerifyAll )
			this._factory.VerifyAll();
		else
			this._factory.Verify();
	}

	/// <summary>
	/// Gets or sets a value indicating whether <see cref="MockFactory.VerifyAll"/> will be used or <see cref="MockFactory.Verify"/>.
	/// </summary>
	/// <value><c>true</c> to use <see cref="MockFactory.VerifyAll"/>; otherwise, <c>false</c>.</value>
	/// <remarks><c>false</c> be default.</remarks>
	public bool VerifyAll { get; set; }

	/// <summary>
	/// Gets or sets the auto mocking container.
	/// </summary>
	/// <value>The auto mocking container.</value>
	protected AutoMockContainer Container { get; private set; }

	/// <summary>
	/// Creates an object of the specified type.
	/// </summary>
	/// <typeparam name="T">A type to create.</typeparam>
	/// <returns>
	/// Object of the type <typeparamref name="T"/>.
	/// </returns>
	/// <remarks>Usually used to create objects to test. Any non-existing dependencies
	/// are mocked.
	/// <para>Container is used to resolve build dependencies.</para></remarks>
	public T Create < T >() where T : class
	{
		return this.Container.Create< T >();
	}

	/// <summary>
	/// Creates an object of the specified type.
	/// </summary>
	/// <typeparam name="T">A type to create.</typeparam>
	/// <param name="activator">The activator used to create object.</param>
	/// <returns>
	/// Object of the type <typeparamref name="T"/>.
	/// </returns>
	/// <remarks>Usually used to create objects to test. Any non-existing dependencies
	/// are mocked.
	/// <para>Container is used to resolve build dependencies.</para></remarks>
	/// <example>Using activator</example>
	/// <code>this.Create( c => new Apple( c.Resolve&lt; ITree> ()) )</code>
	/// <seealso href="http://code.google.com/p/autofac/wiki/ResolveParameters"/>
	public T Create < T > ( Func< IResolve, T > activator ) where T : class
	{
		return this.Container.Create( activator );
	}

	/// <summary>
	/// Resolves an object from the container.
	/// </summary>
	/// <typeparam name="T">Type to resolve for.</typeparam>
	/// <returns>Resolved object.</returns>
	public T Resolve < T >() where T : class
	{
		return this.Container.Resolve< T >();
	}

	/// <summary>
	/// Creates a mock object.
	/// </summary>
	/// <typeparam name="T">A type to mock.</typeparam>
	/// <returns>Mocked object of the type <typeparamref name="T"/>.</returns>
	/// <remarks>Used to set-up expected mock behavior when object created with <see cref="Create{T}()"/>.
	/// calls on the mock.
	/// <para>To set-up expected calls to mock use
	/// <code>Mock&lt; type >().Expect( x => x.Method( params )).Returns( fakeResults )</code></para></remarks>
	public Mock< T > Mock < T >() where T : class
	{
		return this.Container.GetMock< T >();
	}

	/// <summary>
	/// Captures which class to use to provide specified service.
	/// </summary>
	/// <typeparam name="TService">The type of the service.</typeparam>
	/// <typeparam name="TImplementation">The type of the implementation.</typeparam>
	public void Register < TService, TImplementation >()
	{
		this.Container.Register< TService, TImplementation >();
	}

	/// <summary>
	/// Captures <paramref name="instance"/> as the object to provide <typeparamref name="TService"/> for mocking.
	/// </summary>
	/// <typeparam name="TService">The type of the service.</typeparam>
	/// <param name="instance">The instance.</param>
	public void Register < TService > ( TService instance )
	{
		this.Container.Register( instance );
	}

	/// <summary>
	/// Registers the given service creation delegate on the container.
	/// </summary>
	/// <typeparam name="TService">Service type.</typeparam>
	public void Register < TService > ( Func< IResolve, TService > activator )
	{
		this.Container.Register( activator );
	}
}

Comment by nicholas.blumhardt, Aug 26, 2008

Hey looks like you guys have done some great work on this! Very clean :)

It would be great to see some advice on where Automocking might be recommended/suitable vs. regular by-hand mocking, or the Builder pattern...

Comment by slava42, Sep 09, 2008

I don't really use regular by-hand or Builder pattern anymore. I think automocking has completely replaced it all for me. I'd say do what feels natural to you.

Comment by ben.taylor.uk, Jan 11, 2009

Thanks for writing this up. It is a very cool feature. I <3 Moq and Autofac :)

I noticed two small typos in this page:

1. "You specify default mock behavior (strict or loose) through by creating" should be "by creating" (i.e. drop the through)? 2. "Bar constructor takes IApple as parameter" should be "Tree" not "Bar"?

Comment by mcintyre321, Jan 29, 2009

Hi I have had a couple of suggestions (see issues paage)

Comment by santosh.benjamin, Feb 15, 2009

Hi, currently it seems like the automocker only creates mocks for dependencies passed in the constructor. is there any way for us to include dependencies that go in via setter injection?

Thanks Benjy

Comment by slava42, Mar 27, 2009

hey. I was away for a while and busy. I'll take a look at all issue and reply sometime in April.


Sign in to add a comment
Hosted by Google Code