c# - 使用 AutoMoq 属性模拟构造函数依赖

标签 c# unit-testing autofixture

我想知道在使用设置 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 是该类的依赖项。

如果是这种情况,则通过构造函数注入(inject) 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 第四定律 constructors should do no work .

关于c# - 使用 AutoMoq 属性模拟构造函数依赖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36918881/

相关文章:

c# - 将 View 绑定(bind)到 ViewModel 时 WPF 中的工具提示内存泄漏

unit-testing - 使模拟实现记录任意数量的参数

java - 为什么 JUnit 从 Eclipse 启动需要这么长时间?

c# - 我怎样才能指示 AutoFixture 不要费心填写一些属性?

c# - 如何统一解决一个接口(interface)的所有实现?

c# - SQL Server错误: The database cannot be opened because it is version 904.如何处理此服务器支持852及更早版本

unit-testing - 运行分析时,Intellij 中的 SonarQube 未获取单元测试分支覆盖率

mocking - 此测试是否正确使用了AutoFixture和Moq?

c# - Autofixture 定制 : provide constructor parameter

c# - 是否可以从 vb.net dll 中的 dll 导入 c# 类?