我已经使用AutoFixture / AutoMoqData / Nunit好几个月了,到目前为止很开心。
但我陷入了一些奇怪的事情:
如果我想在测试套件中运行单个测试(使用TestDriven),似乎AutoMoqData属性多次启动(5到9之间,但我不知道为什么,以及决定了多少它运行的时间。)
问题在于,如果我尝试在AutoFixture自定义项中冻结对象实例,它将使用这么多的fixture实例冻结5到9个对象,并且不知道在我的测试中注入了哪一个。< / p>
有没有办法避免这种情况?为什么会在第一时间发生?
示例代码:
public class AutoMoqDataAttribute : AutoDataAttribute
{
public AutoMoqDataAttribute()
: base(new Fixture()
.Customize(new AutoMoqCustomization())
.Customize(new FrozenFooCustomization()) // freezing an object
.Customize(new FrozenFixtureCustomization()) // freezing the passed fixture to have the fixture instance available in the test body
.Customize(new StaticBindingCustomization()) // binding the frozen object to a static reference
)
{
}
}
public class FrozenFooCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Freeze<Foo>();
}
}
public class Foo { }
public class FrozenFixtureCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Inject(fixture);
}
}
public class StaticBindingCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Freeze<Mock<ISomeUtilities>>();
var someUtilities = fixture.Create<Mock<ISomeUtilities>>();
someUtilities.Setup(x => x.GetStuff()).Returns(fixture.Create<Foo>());
// this is executed several times, each time with a different instance of fixture, returning a different instance of Foo
SomeExtensions.Factory = x => someUtilities.Object;
// so the last "someUtilities.Object" is bound to the factory, but the test relies on a frozen version generated by one of the previous fixture instances
}
}
[TestFixture]
public class Test
{
[Test, AutoMoqData]
public void SomeTest(
[Frozen]Mock<ISomeUtilities> objMock,
SomeObjectToTest sut)
{
Assert.IsTrue(ReferenceEquals(objMock.Object.GetStuff(), sut.GetStuff()));
}
}
public class SomeObjectToTest { }
public static class SomeExtensions
{
public static Func<object, ISomeUtilities> Factory { get; set; } = x => new SomeUtilities(x);
public static object GetStuff(this object obj)
{
return Factory(obj).GetStuff();
}
}
public class SomeUtilities : ISomeUtilities
{
private readonly object _obj;
public SomeUtilities(object obj)
{
_obj = obj;
}
public object GetStuff()
{
return _obj; // whatever
}
}
public interface ISomeUtilities
{
object GetStuff();
}
编辑:SomeExtensions.Factory是一个工厂,用于根据Daniel Cazzulino's approach使扩展可模拟。
我不是那些扩展的忠实粉丝,并希望在某些时候重构它们,但这是另一次。这里的问题是为什么有几个夹具实例,使得工厂中使用的冻结SomeUtilities模拟不同于测试中使用的模拟实例,因此测试失败。
EDIT2:根据@MarkSeemann的建议,我在Autofixture repo报告了一个问题。