项目
版本

Autofac Moq

Moq 集成包允许你在单元测试中使用 Autofac 容器自动为具体实例和 mock 抽象实例创建依赖项。你可以从 NuGet 获取 Autofac.Extras.Moq 包。

入门

假设你有一个要测试的系统和一个依赖项:

public class SystemUnderTest
{
    public SystemUnderTest(IDependency dependency)
    {
    }
}

public interface IDependency
{
}

在编写单元测试时,使用 Autofac.Extras.Moq.AutoMock 类来实例化系统。这样会自动为你构造函数注入一个模拟的依赖项。当你创建 AutoMock 工厂时,你可以指定默认的模拟行为:

  • AutoMock.GetLoose() - 使用松散模拟行为创建自动模拟。
  • AutoMock.GetStrict() - 使用严格模拟行为创建自动模拟。
  • AutoMock.GetFromRepository(repo) - 根据现有配置的存储库创建模拟。
[Test]
public void Test()
{
    using (var mock = AutoMock.GetLoose())
    {
        // AutoMock 类将向 SystemUnderTest 构造函数注入一个 IDependency 模拟
        var sut = mock.Create<SystemUnderTest>();
    }
}

配置模拟

你可以像使用 Moq 一样配置自动模拟并/或对其进行断言。

[Test]
public void Test()
{
    using (var mock = AutoMock.GetLoose())
    {
        // 安排 - 配置模拟
        mock.Mock<IDependency>().Setup(x => x.GetValue()).Returns("预期值");
        var sut = mock.Create<SystemUnderTest>();

        // 执行
        var actual = sut.DoWork();

        // 断言 - 断言模拟
        mock.Mock<IDependency>().Verify(x => x.GetValue());
        Assert.AreEqual("预期值", actual);
    }
}

public class SystemUnderTest
{
    private readonly IDependency dependency;

    public SystemUnderTest(IDependency strings)
    {
        this.dependency = strings;
    }

    public string DoWork()
    {
        return this.dependency.GetValue();
    }
}

public interface IDependency
{
    string GetValue();
}

配置特定依赖项

你可以使用 GetLooseGetStrictGetFromRepository 方法的 beforeBuild 回调参数来配置 AutoMock ,为特定服务类型提供特定的实例(或应用其他注册行为),这类似于配置新的生命周期范围:

[Test]
public void Test()
{
    var dependency = new Dependency();
    using (var mock = AutoMock.GetLoose(cfg => cfg.RegisterInstance(dependency).As<IDependency>()))
    {
        // 返回你的注册实例。
        var dep = mock.Create<IDependency>();

        // 如果SystemUnderTest依赖于IDependency,它将获得你的依赖项实例。
        var underTest = mock.Create<SystemUnderTest>();

        // ...以及其他测试内容。
    }
}

传递给回调的 cfg 参数是一个普通的 Autofac ContainerBuilder 实例,所以你可以像在正常设置中那样进行任何注册行为。

你还可以通过 RegisterMock 扩展方法配置 AutoMock 使用任何现有的模拟:

[Test]
public void Test()
{
    var mockA = new Mock<IServiceA>();
    mockA.Setup(x => x.RunA());

    // mockA自动注册为提供IServiceA
    using (var mock = AutoMock.GetLoose(cfg => cfg.RegisterMock(mockA)))
    {
        // mockA将作为IServiceA注入到TestComponent中
        var component = mock.Create<TestComponent>();

        // ...以及其他测试内容
    }
}
在本文档中