Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add a specific implementation of a Mock created with Autofixture?

I am writing tests for class (lets call it Sut) which has some dependencies injected via constructors. For this class I have to use the constructor with the most parameters, therefore I used the AutoMoqDataAttributeGreedy implementation:

public class AutoMoqDataAttribute : AutoDataAttribute
{
    public AutoMoqDataAttribute() : base(new Fixture().Customize(new AutoMoqCustomization()))
    {
    }
}

public class AutoMoqDataAttributeGreedy : AutoDataAttribute
{
    public AutoMoqDataAttributeGreedy() : base(new Fixture(new GreedyEngineParts()).Customize(new AutoMoqCustomization()))
    {
    }
}

The constructor of my sut looks like this:

public class Sut(IInerface1 interface1, IInterface2 interface2, IInterface3 interface3)
{
    Interface1 = interface1;
    Interface2 = interface2;
    Interface3 = interface3;
}

One example test looks like this:

[Theory, AutoMoqDataAttributeGreedy]
public void SomeTest([Frozen]Mock<IInterface1> mock1 ,
                      Mock<IInterface2> mock2, 
                      Sut sut, 
                      SomOtherdata data)
{
    // mock1 and mock2 Setup omitted

    // I want to avoid following line
    sut.AddSpeficicInterfaceImplementation(new IInterface3TestImplementation());

    sut.MethodIWantToTest();

    //Assert omitted 
}

The problem is that I need a specific implementation of IInterface3 for testing and I want to avoid adding a method to my SUT (Interface3TestImplementation) only for my unit test and I also I want to avoid repeating code since I have to add this instance in each and every test.

Is there a nice and neat way to have this implementation being added for all my test / for specific tests with Autofixture?

like image 477
zlZimon Avatar asked Jan 14 '16 11:01

zlZimon


People also ask

Why use AutoFixture?

AutoFixture is a library that you can use alongside your testing framework to reduce the amount of boilerplate test code you need to write and thus improve your productivity. At its core, AutoFixture helps you setup your tests by generating anonymous test data for you.

What is Auto Fixture?

AutoFixture is an open source library for . NET designed to minimize the 'Arrange' phase of your unit tests in order to maximize maintainability.

What is AutoFixture xunit?

AutoFixture is a tool designed to make Test-Driven Development more productive and unit tests more refactoring-safe.

What is AutoMoqCustomization?

The AutoMoqCustomization is the core of the integration of AutoFixture with Moq. By adding an instance of this class to the fixture, requests for non-concrete types will be handled by Moq. var fixture = new Fixture();


2 Answers

If you need to do this as a one-off test, then the answer by Enrico Campidoglio is the way to go.

If you need this as a general rule throughout all of your unit tests, you can customize the Fixture with a TypeRelay:

fixture.Customizations.Add(
    new TypeRelay(
        typeof(IInterface3),
        typeof(IInterface3TestImplementation));

This will change fixture so that, whenever IInterface3 is needed, an instance of IInterface3TestImplementation will be created and used.

like image 123
Mark Seemann Avatar answered Sep 19 '22 14:09

Mark Seemann


Using your IFixture that you have created, you can call .Register against a specific interface and supply the object to use when that interface is then subsequently used.

e.g.

_fixture = new Fixture().Customize(new AutoMoqCustomization());
_fixture.Register<Interface3>(() => yourConcreteImplementation);

You could also use mocking that would allow you to then use .Freeze on the fixture and that way you could just set some expected calls against the interface and wouldn't need a completely concrete instance. You could let AutoFixture create a default implementation for you and apply the setup that you configured.

e.g.

var mockedInterface = _fixture.Freeze<Mock<Interface3>>();
mockedInterface
    .Setup(x => x.PropertyOnInterface)
    .Returns("some value");
like image 41
Emma Middlebrook Avatar answered Sep 19 '22 14:09

Emma Middlebrook