AnonAll112
AnonAll112

Reputation: 13

AutoFixture and dynamic fixture type Injections

I am very new to AutoFixture and am having some issues trying to dynamically Freeze and Inject types. Here is an example of the code I had that I was repeating all over the place to get fake repositories injected into my fixture:

FakeRepository<Application> applicationRepository = fixture.Freeze<FakeRepository<Application>>();
fixture.Inject<IReadRepository<Application>>(applicationRepository);
fixture.Inject<IWriteRepository<Application>>(applicationRepository);

After getting all of the types in the entity assembly dynamically using reflection, I would like to do something like this:

Type repositoryReadInterfaceType = typeof(IReadRepository<>).MakeGenericType(entityType);
Type repositoryWriteInterfaceType = typeof(IWriteRepository<>).MakeGenericType(entityType);
Type repositoryType = typeof(FakeRepository<>).MakeGenericType(entityType);

var repositoryObject = fixture.Freeze(repositoryType);
fixture.Inject(repositoryReadInterfaceType, repositoryObject);
fixture.Inject(repositoryWriteInterfaceType, repositoryObject);

However, there are no overloads which support the desired injections I would like. Is there any other way of going about this that I'm missing? Or, perhaps, is this just not possible?

Edit for what I have tried:

Attempt 1 using TypeRelay:

var repositoryObject = fixture.Freeze(repositoryType);

fixture.Customizations.Add(new TypeRelay(repositoryReadInterfaceType, repositoryType));
fixture.Customizations.Add(new TypeRelay(repositoryWriteInterfaceType, repositoryType));

Attempt 2 using SpecimenBuilderNodeFactory:

var repositoryObject = fixture.Freeze(repositoryType);

fixture.Customizations.Insert(
    0,
    SpecimenBuilderNodeFactory.CreateTypedNode(
        repositoryReadInterfaceType,
        new FixedBuilder(repositoryObject)
    )
);
fixture.Customizations.Insert(
    0,
    SpecimenBuilderNodeFactory.CreateTypedNode(
        repositoryWriteInterfaceType,
        new FixedBuilder(repositoryObject)
    )
);

Attempt 3 of just using dynamic Freezing:

In a separate method using Reflection, I am freezing all of the fake repositories like so:

var repositoryObject = fixture.Freeze(repositoryType);

Then in my main method I am injecting the read and write repository types manually:

fixture.Inject<IReadRepository<Application>>(fixture.Create<FakeRepository<Application>>());
fixture.Inject<IWriteRepository<Application>>(fixture.Create<FakeRepository<Application>>());

All of the above attempts result in the Read and Write types seeming to not point at the same FakeRepository.

Upvotes: 1

Views: 1213

Answers (1)

Mark Seemann
Mark Seemann

Reputation: 233367

Updated answer, original further down

This repro works (the tests passes):

public interface IFoo
{
    string FooIt();
}

public interface IBar
{
    string BarIt();
}

public class FooBar : IFoo, IBar
{
    public FooBar(Guid id)
    {
        this.Id = id;
    }

    public Guid Id { get; private set; }

    public string BarIt()
    {
        return this.Id.ToString();
    }

    public string FooIt()
    {
        return this.Id.ToString();
    }
}

public class Tests
{
    [Fact]
    public void AllIsFrozen()
    {
        var fixture = new Fixture();
        fixture.Customize(new FreezingCustomization(typeof(FooBar)));
        fixture.Customizations.Add(new TypeRelay(typeof(IFoo), typeof(FooBar)));
        fixture.Customizations.Add(new TypeRelay(typeof(IBar), typeof(FooBar)));

        var foo = fixture.Create<IFoo>();
        var bar = fixture.Create<IBar>();
        var foobar = fixture.Create<FooBar>();

        Assert.Equal(foobar.Id.ToString(), foo.FooIt());
        Assert.Equal(foobar.Id.ToString(), bar.BarIt());
    }
}

Original answer

I haven't tried this, so it may neither compile, nor work...

Everything you inject is eventually packaged into an ISpecimenBuilder and placed in Fixture.Customizations. You could try to use a FixedBuilder and package that into a typed node.

Something like this could work:

fixture.Customizations.Insert(
    0,
    SpecimenBuilderNodeFactory.CreateTypedNode(
        myType,
        new FixedBuilder(myObject)));

You could also use Customizations.Add, but note that the order in that collection matters (the first match wins).

Upvotes: 1

Related Questions