5
votes

I'm trying to write a suite of database integration tests for my domain which uses Entity Framework. I would prefer to autofixture objects in some scenarios. My ideal syntax would be something like

[TestMethod]
public void AutofixtureMyEntityEntity()
{
    var fixture = new Fixture();

    fixture.Customize<MyEntity>(
      c => c.FromFactory<MyDbContext>(ctx => ctx.Set<MyEntity>().Create()));

    using (var context = new MyDbContext())
    {
        fixture.Inject(context);
        var entity = fixture.CreateAnonymous<MyEntity>();
        context.Set<MyEntity>().Add(entity);
        context.SaveChanges();
    }
}

[TestMethod]    
[ExpectedException(typeof(InvalidOperationException))]
public void AutoFixtureMyEntityEntityWithoutInjection()
{
    var fixture = new Fixture();

    fixture.Customize<MyEntity>(
       c => c.FromFactory<MyDbContext>(ctx => ctx.Set<MyEntity>().Create()));

    using (var context = new MyDbContext())
    {
        var entity = fixture.CreateAnonymous<MyEntity>();
        context.Set<MyEntity>().Add(entity);
        context.SaveChanges();
    }
}

Obviously, that isn't working since CreateAnonymous() isn't expecting the input parameter for the factory. I can only assume that i have a flawed understanding of what FromFactory() provides. Although the comment reads,

/// Specifies that a specimen should be created in a particular way, using a single input
/// parameter for the factory.

After reading ploehs blog, I'm slightly more confused on how these pieces interact with each other.

The instance of MyDbContext during factory invocation is not the instance I passed to Inject()

1
You can use fixture.Inject( context) which will mean that any requirement for a Context will use that instance. Would that work? (To be honest your question is quite muddled - you have loads of proposed approaches and its good to know you've tried, but the single problem you have isnt 100% clear to me)Ruben Bartelink
Ruben, I tried to tighten up the example. Messed around with Inject quite a bit without any luck, i'm trying to supply an instance to the factory potentially before each call to create anonymous.AndrewBoudreau

1 Answers

7
votes

Would something like this work?

var fixture = new Fixture();
fixture.Customize<MyEntity>(c => c
    .FromFactory<MyDbContext, MyEntity>(ctx => ctx.Set<MyEntity>.Create()));

using (var context = new MyDbContext())
{
    fixture.Inject(context);
    var item = fixture.CreateAnonymous<MyEntity>();
    context.Set<MyEntity>().Add(item);
    context.SaveChanges();
}

Disclaimer: I haven't tried to compile this...


FWIW, if you were using xUnit.net with AutoFixture, you could reduce the test to something like:

[Theory, MyAutoData]
public void TheTest([Frozen]MyDbContext context, MyEntity item)
{
    context.Set<MyEntity>().Add(item);
    context.SaveChanges();
}