Question

I'm using AutoFixture for few weeks now and I wonder whether it's better to use a new Fixture for each object I want to create or I can just reuse the fixture I customized?

Here are few different approaches.

Reuse the same fixture.

Fixture fixture = new Fixture();

ActionExecutedContext context = fixture.Customize(new CustomActionResult<RedirectResult>("Controller/Action"))
                                       .Customize(new CustomController())
                                       .Customize(new CustomActionExecutedContext())
                                       .Create<ActionExecutedContext>();

ExportModelStateToTempDataAttribute attribute = fixture.Create<ExportModelStateToTempDataAttribute>();

Create a new fixture per object. (Not sure whether it make sense because I see no reason to do that.)

ActionExecutedContext context = new Fixture().Customize(new CustomActionResult<RedirectResult>("Controller/Action"))
                                                             .Customize(new CustomController())
                                                             .Customize(new CustomActionExecutedContext())
                                                             .Create<ActionExecutedContext>();

ExportModelStateToTempDataAttribute attribute = new Fixture().Create<ExportModelStateToTempDataAttribute>();

Create the SUT with the new keyword.

ActionExecutedContext context = new Fixture().Customize(new CustomActionResult<RedirectResult>("Controller/Action"))
                                                             .Customize(new CustomController())
                                                             .Customize(new CustomActionExecutedContext())
                                                             .Create<ActionExecutedContext>();

ExportModelStateToTempDataAttribute attribute = new ExportModelStateToTempDataAttribute();

Here is the complete test.

[Fact]
public void Should_not_set_the_temp_data_when_the_model_is_valid()
{
    // Arrange
    Fixture fixture = new Fixture();

    ActionExecutedContext context = fixture.Customize(new CustomActionResult<RedirectResult>("Controller/Action"))
                                           .Customize(new CustomController())
                                           .Customize(new CustomActionExecutedContext())
                                           .Create<ActionExecutedContext>();

    ExportModelStateToTempDataAttribute attribute = new ExportModelStateToTempDataAttribute();

    // Act
    attribute.OnActionExecuted(context);

    // Assert
    context.Controller.TempData.Should().HaveCount(0);
}
Was it helpful?

Solution

The idiomatic usage of AutoFixture is to use a shared instance of the Fixture class per test method.

So, while all the examples are technically correct, the last one tends to be more idiomatic as it doesn't use any shared state.


In fact, you can take advantage of the AutoFixture.Xunit glue library:

PM> Install-Package AutoFixture.Xunit

Although I haven't tried to compile this, the example test could be rewritten as:

[Theory, TestConventions]
public void Should_not_set_the_temp_data_when_the_model_is_valid(
    ActionExecutedContext context,
    ExportModelStateToTempDataAttribute attribute)
{
    attribute.OnActionExecuted(context);
    context.Controller.TempData.Should().HaveCount(0);
}

Where TestConventions is defined as:

internal class TestConventionsAttribute : AutoDataAttribute
{
    internal TestConventionsAttribute() 
        : base(
            new Fixture()
                .Customize(new CustomActionResult<RedirectResult>(
                               "Controller/Action"))
                .Customize(new CustomController())
                .Customize(new CustomActionExecutedContext()))
    {
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top