Although it's currently not built-in, it's easy to write a general purpose Decorator that freezes objects as they leave the AutoFixture Tree of Responsibility:
public class MemoizingBuilder : ISpecimenBuilder
{
private readonly ISpecimenBuilder builder;
private readonly ConcurrentDictionary<object, object> instances;
public MemoizingBuilder(ISpecimenBuilder builder)
{
this.builder = builder;
this.instances = new ConcurrentDictionary<object, object>();
}
public object Create(object request, ISpecimenContext context)
{
return this.instances.GetOrAdd(
request,
r => this.builder.Create(r, context));
}
}
Notice that it Decorates another ISpecimenBuilder
, but remembers all values before it returns them. If the same request arrives again, it'll return the memoized value.
While you can't extend AutoMoqCustomization
, you can replicate what it does (it's only two lines of code), and use the MemoizingBuilder
around it:
public class AutoFreezeMoq : ICustomization
{
public void Customize(IFixture fixture)
{
if (fixture == null)
throw new ArgumentNullException("fixture");
fixture.Customizations.Add(
new MemoizingBuilder(
new MockPostprocessor(
new MethodInvoker(
new MockConstructorQuery()))));
fixture.ResidueCollectors.Add(new MockRelay());
}
}
Use this AutoFreezeMoq
instead of AutoMoqCustomization
. It will freeze all mocks, and all interfaces and abstract base classes created from those mocks.
public class AutoMoqDataAttribute : AutoDataAttribute
{
public AutoMoqDataAttribute()
: base(new Fixture().Customize(new AutoFreezeMoq()))
{
}
}