我单元测试一个类,它将工厂作为其中一个依赖项,并使用它来构建SUT
有效控制的对象:
class SystemUnderTest
{
private readonly IFoo foo1;
private readonly IFoo foo2;
public SystemUnderTest(IFooFactory fooFactory)
{
this.foo1 = fooFactory.Build("Bar1");
this.foo2 = fooFactory.Build("Bar2");
}
public IFoo Foo1
{
get
{
return this.foo1;
}
}
...
}
SystemUnderTest
对象具有单个生命周期,该生命周期注入多个ViewModels
,使用它的属性/方法执行不同的操作,因此这有效地排除了定义{{1} } class,这样我就可以注入Provider
和foo1
,而无需在构造函数中与工厂进行交互,这是我在面对这个问题时通常会做的事情。
但是通过注入工厂,我无法弄清foo2
如何正确配置AutoFixture
以提供正确的fooFactory
并将其作为方法参数传递到我的测试中如:
IFoo
我知道我可以扩展[Theory]
[AutoData]
internal void Foo1_IsCorrectlyPopulated_Test(
[Frozen] IFoo foo1,
SystemUnderTest systemUnderTest)
{
var actual = systemUnderTest.Foo1;
Assert.Same(foo1, actual);
}
属性并为Fixture提供我自己的自定义,例如:
AutoData
但是我想知道是否有能力获取我在属性构造函数中创建的class SystemUnderTestAutoDataAttribute : AutoDataAttribute
{
public SystemUnderTestAutoData()
{
var fooFactory = this.Fixture.Freeze<IFooFactory>();
var foo1 = this.Fixture.Create<IFoo>();
Mock.Get(fooFactory).Setup(m => m.Build("Bar1")).Returns(foo1);
}
}
对象并将其作为参数传递给测试方法?我知道我可以foo1
Freeze
对象,但这意味着我需要为foo1
和foo1
提供两个属性类,以便为我的测试方法提供正确的信息当我必须在我的测试用例中使用这两个对象时,这就失败了。
我希望有一种方法可以使用特定名称(或其他匹配方法)创建对象,并在测试用例中匹配(不编译):
foo2
那么任何具有名称(或其他匹配方法)的匹配注册实例都可以作为测试用例参数的一部分进行解析?
答案 0 :(得分:3)
以下内容应该有效。首先,定义一个[AutoMoqData]
属性,如下所示:
public class AutoMoqDataAttribute : AutoDataAttribute
{
public AutoMoqDataAttribute()
: base(new Fixture().Customize(new AutoMoqCustomization()))
{
}
}
其次,按照以下方式编写测试:
[Theory, AutoMoqData]
public void MyTest([Frozen]Mock<IFooFactory> td, IFoo foo1, IFoo foo2, IFixture fixture)
{
td.Setup(f => f.Build("Bar1")).Returns(foo1);
td.Setup(f => f.Build("Bar2")).Returns(foo2);
var sut = fixture.Create<SystemUnderTest>();
// Rest of test...
}
也就是说,使用工厂来处理终身问题几乎总是一种设计气味。 OP中的特定设计违反了Nikola Malovic's 4th law of IoC。考虑将对象的设计与其生命周期管理分开。一种方法是使用Decoraptor。