我想知道是否有一种方法可以在使用设置AutoData
的测试用例时在调用被测系统(SUT)的构造函数之前为依赖项设置模拟。
我的SUT看起来像:
class Sut
{
private readonly IFoo foo;
public Sut(IFooFactory factory)
{
this.foo = factory.Build(1, 2);
}
public IFoo Foo
{
get
{
return this.foo;
}
}
}
因此,我正在编写的测试如下所示:
[Theory]
[AutoData]
internal void Foo_IsCorrectlySet_Test(
[Frozen] Mock<IFooFactory> fooFactory,
IFoo foo,
Sut sut)
{
fooFactory.Setup(mock => mock.Build(1, 2))
.Returns(foo)
.Verifiable();
var actual = sut.Foo;
Assert.Equal(foo, sut);
fooFactory.Verify();
}
显然,由于
Sut
的构造函数在我能够设置IFooFactory
之前运行,因此该测试失败。因此,我认为我可以在测试中将Sut
的声明更改为Lazy<Sut>
。但是构造函数仍然在实际测试代码运行之前运行,这意味着我的测试将失败。
现在,我知道我可以轻松地使用实际的
Fixture
对象设置此测试,并手动创建所有对象并进行设置,然后再调用创建Sut
,这很好,但我想保留所有测试大致相同,因此我想知道是否存在一种方法,我仍然可以使用AutoData
属性设置测试,但在完成所有设置之后才运行构造函数? 最佳答案
AutoFixture最初是作为用于测试驱动开发(TDD)的工具而构建的,而TDD只是关于反馈的。本着GOOS的精神,您应该听听测试。如果测试很难编写,则应考虑API设计。 AutoFixture倾向于放大这种反馈,在这里也可能是这种情况。
考虑Sut
类的不变量。由于它具有只读的IFoo
类字段,因此我将其解释为IFoo
是该类的依赖项的强烈指示。
如果是这种情况,请通过构造函数而不是IFoo
注入IFooFactory
:
public class Sut
{
private readonly IFoo foo;
public Sut(IFoo foo)
{
this.foo = foo;
}
public IFoo Foo
{
get { return this.foo; }
}
}
您仍然可以在应用程序的Composition Root中使用
IFooFactory
编写它:var sut = new Sut(aFactory.Build(1, 2));
这将使测试更易于编写。我什至无法向您展示上述重构后的测试结果,因为它是多余的,可以(并且应该)删除。
FWIW,上面提出的原始设计违反了Nikola Malovic的IoC的第4条定律constructors should do no work。
关于c# - 使用AutoMoq属性模拟构造函数依赖项,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36918881/