Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
2016-05-30-automocked-base-class-for-nunit-tests
namespace ConductOfCode
{
public class HelloWorld
{
private readonly IFoo _foo;
private readonly IBar _bar;
public HelloWorld(IFoo foo, IBar bar)
{
_foo = foo;
_bar = bar;
}
public string GetMessage()
{
return _foo.GetFoo() + _bar.GetBar();
}
}
public interface IFoo
{
string GetFoo();
}
public interface IBar
{
string GetBar();
}
}
using ConductOfCode.Fakes;
using Moq;
using NUnit.Framework;
using Should;
namespace ConductOfCode.Tests.Given_HelloWorld_WithSubject
{
public class When_GetMessage : WithSubject<HelloWorld>
{
[SetUp]
public void SetUp()
{
The<IFoo>().Setup(x => x.GetFoo()).Returns("Hello");
With<IBar>(x => x.GetBar() == ", World!");
}
[Test]
public void Should_invoke_IFoo_GetMessage()
{
Subject.GetMessage();
The<IFoo>().Verify(x => x.GetFoo());
}
[Test]
public void Should_invoke_IBar_GetMessage()
{
Subject.GetMessage();
The<IBar>().Verify(x => x.GetBar(), Times.Once);
}
[Test]
public void Should_return_a_concatenated_string_with_messages_from_IFoo_and_IBar()
{
Subject.GetMessage().ShouldEqual("Hello, World!");
}
}
}
using System;
using System.Linq.Expressions;
using Moq;
using Moq.AutoMock;
using NUnit.Framework;
namespace ConductOfCode.Fakes
{
/// <summary>
/// Base class that adds auto mocking/faking to NUnit.
/// </summary>
/// <typeparam name="TSubject">
/// The subject of the specification. This is the type that is created by the specification for you.
/// </typeparam>
public abstract class WithSubject<TSubject> where TSubject : class
{
private AutoMocker _mocker;
private TSubject _subject;
/// <summary>
/// Gives access to the subject under specification. On first access
/// the spec tries to create an instance of the subject type by itself.
/// </summary>
protected TSubject Subject => _subject ?? (_subject = _mocker.CreateInstance<TSubject>());
[SetUp]
public void Setup()
{
_mocker = new AutoMocker();
}
[TearDown]
public void TearDown()
{
_subject = null;
}
/// <summary>
/// Creates a fake of the type specified by <typeparamref name="TInterfaceType" />.
/// This method reuses existing instances. If an instance of <typeparamref name="TInterfaceType" />
/// was already requested it's returned here. (You can say this is kind of a singleton behavior)
/// Besides that, you can obtain a reference to injected instances/fakes with this method.
/// </summary>
/// <typeparam name="TInterfaceType">The type to create a fake for. (Should be an interface or an abstract class)</typeparam>
/// <returns>
/// An instance implementing <typeparamref name="TInterfaceType" />.
/// </returns>
protected Mock<TInterfaceType> The<TInterfaceType>() where TInterfaceType : class
{
return _mocker.GetMock<TInterfaceType>();
}
/// <summary>
/// Configures the specification to use the specified instance for <typeparamref name="TInterfaceType" />.
/// </summary>
/// <typeparam name="TInterfaceType">The type to inject.</typeparam>
/// <param name="instance">The instance to inject.</param>
protected void With<TInterfaceType>(TInterfaceType instance)
{
_mocker.Use(instance);
}
/// <summary>
/// Configures the specification to use the specified mock for <typeparamref name="TInterfaceType" />.
/// </summary>
/// <typeparam name="TInterfaceType">The type to inject.</typeparam>
/// <param name="mock">The mock to inject.</param>
protected void With<TInterfaceType>(Mock<TInterfaceType> mock) where TInterfaceType : class
{
_mocker.Use(mock);
}
/// <summary>
/// Configures the specification to setup a mock with specified behavior for <typeparamref name="TInterfaceType" />.
/// </summary>
/// <typeparam name="TInterfaceType">The type to inject.</typeparam>
/// <param name="setup">The behavior to inject.</param>
protected void With<TInterfaceType>(Expression<Func<TInterfaceType, bool>> setup) where TInterfaceType : class
{
_mocker.Use(setup);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.