Reputation: 13
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
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