我想知道,在使用设置AutoData的测试用例之前,在调用测试下系统的构造函数(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属性来设置测试,但在所有设置完成之后才运行构造函数?
发布于 2016-04-28 20:32:18
AutoFixture最初是作为测试驱动开发( TDD )工具构建的,而TDD完全是关于反馈的。本着古斯的精神,您应该听您的测试。如果测试很难编写,您应该考虑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; }
}
}您仍然可以在应用程序的IFooFactory中使用成分根编写它
var sut = new Sut(aFactory.Build(1, 2));这将使测试更易于编写。我甚至不能向您展示这个重构的上述测试,因为它是多余的,可以(而且应该)删除。
上述最初的设计违反了尼古拉·马洛维奇( Nikola )关于IoC的第四定律,即构造函数不应该做任何工作。。
发布于 2016-04-28 15:25:50
您可以使用夹具对象模式。这允许您在创建sut之前设置您的模拟程序。
行文中的某物:
private class Fixture
{
public Mock<FooFactory> FooFactoryMock { get; set; } = new Mock<FooFactory>();
public Sut GetSut()
{
return new Sut(FooFactoryMock.Object);
}
}
[Theory]
[AutoData]
internal void Foo_IsCorrectlySet_Test(
IFoo foo)
{
var fixture = new Fixture();
fixture.FooFactory.Setup(mock => mock.Build(1, 2))
.Returns(foo)
.Verifiable();
var sut = fixture.GetSut();
var actual = sut.Foo;
Assert.Equal(foo, sut);
fooFactory.Verify();
}https://stackoverflow.com/questions/36918881
复制相似问题