In fact, this can be done with AutoFixture, but this requires a little setup. There are all extensibility points, but I admit that in this case the solution is not particularly accessible for detection.
This gets even more complicated if you want it to work with nested / complex types.
Given the MyObject
class above, as well as this MyParent
class:
public class MyParent { public MyObject Object { get; set; } public string Text { get; set; } }
All of these unit tests pass:
public class Scenario { [Fact] public void CreateMyObject() { var fixture = new Fixture().Customize(new MockHybridCustomization()); var actual = fixture.CreateAnonymous<MyObject>(); Assert.NotNull(actual.A); Assert.NotNull(actual.B); Assert.NotNull(actual.C); } [Fact] public void MyObjectIsMock() { var fixture = new Fixture().Customize(new MockHybridCustomization()); var actual = fixture.CreateAnonymous<MyObject>(); Assert.NotNull(Mock.Get(actual)); } [Fact] public void CreateMyParent() { var fixture = new Fixture().Customize(new MockHybridCustomization()); var actual = fixture.CreateAnonymous<MyParent>(); Assert.NotNull(actual.Object); Assert.NotNull(actual.Text); Assert.NotNull(Mock.Get(actual.Object)); } [Fact] public void MyParentIsMock() { var fixture = new Fixture().Customize(new MockHybridCustomization()); var actual = fixture.CreateAnonymous<MyParent>(); Assert.NotNull(Mock.Get(actual)); } }
What's in MockHybridCustomization? It:
public class MockHybridCustomization : ICustomization { public void Customize(IFixture fixture) { fixture.Customizations.Add( new MockPostprocessor( new MethodInvoker( new MockConstructorQuery()))); fixture.Customizations.Add( new Postprocessor( new MockRelay(t => t == typeof(MyObject) || t == typeof(MyParent)), new AutoExceptMoqPropertiesCommand().Execute, new AnyTypeSpecification())); } }
The MockPostprocessor
, MockConstructorQuery
and MockRelay
defined in the AutoMoq extension in AutoFixture, so you will need to add a link to this library. However, note that AutoMoqCustomization
not required to be AutoMoqCustomization
.
The AutoExceptMoqPropertiesCommand
class AutoExceptMoqPropertiesCommand
also configurable for this occasion:
public class AutoExceptMoqPropertiesCommand : AutoPropertiesCommand<object> { public AutoExceptMoqPropertiesCommand() : base(new NoInterceptorsSpecification()) { } protected override Type GetSpecimenType(object specimen) { return specimen.GetType(); } private class NoInterceptorsSpecification : IRequestSpecification { public bool IsSatisfiedBy(object request) { var fi = request as FieldInfo; if (fi != null) { if (fi.Name == "__interceptors") return false; } return true; } } }
This solution provides a general solution to the issue. However, it has not been thoroughly tested, so I would like to receive feedback from it.