c# – 使用Moq和Unity进行单元测试的Mock仓库对象的正确方法

在我的工作,我们使用Moq嘲笑和Unity为IOC容器。我对此相当新,没有很多资源在工作,帮助我确定我应该使用的最佳做法。

现在,我有一组存储库接口(Ex:IRepository1,IRepository2 … IRepository4),特定进程需要使用它来完成它的工作。

在实际代码中,我可以通过使用IOC容器并使用RegisterType()方法来确定所有IRepository对象。

我试图找出最好的方法,以便能够测试需要4个提到的存储库的方法。

我想我可以只注册一个Unity IOC容器的一个新实例,并在容器上调用RegisterInstance,为每个mock对象传递Mock.Object值。我试图使这个注册过程可重用,所以我不必一直做同样的事情每次单元测试,除非单元测试需要一些特定的数据从存储库返回。这是问题所在。什么是在模拟存储库上设置期望值的最佳实践?看起来像,如果我只是调用在Unity容器上的RegisterType,我将失去对实际Mock对象的引用,并将无法覆盖行为。

最佳答案
单元测试不应该使用容器。依赖注入(DI)分为两个阶段:

>使用DI模式将依赖注入到消费者。你不需要一个容器来做到这一点。
>在应用程序的Composition Root,使用DI容器(或穷人的DI)将所有组件连接在一起。

如何不使用任何DI容器进行单元测试

例如,考虑使用IRepository1的类。通过使用构造函数注入模式,我们可以使依赖关系作为类的不变量。

public class SomeClass
{
    private readonly IRepository1 repository;

    public SomeClass(IRepository1 repository)
    {
        if (repository == null)
        {
            throw new ArgumentNullException("repository");
        }

        this.repository = repository;
    }

    // More members...
}

请注意,readonly关键字与Guard子句组合可确保如果成功实例化实例,则存储库字段不为空。

您不需要容器来创建MyClass的新实例。你可以直接从使用Moq或另一个测试双单元测试单元测试:

[TestMethod]
public void Test6()
{
    var repStub = new Mock<IRepository1>();
    var sut = new SomeClass(repStub.Object);
    // The rest of the test...
}

有关详细信息,请参阅here

如何使用Unity进行单元测试

但是,如果您绝对必须在测试中使用Unity,则可以创建容器并使用RegisterInstance方法:

[TestMethod]
public void Test7()
{
    var repMock = new Mock<IRepository1>();

    var container = new UnityContainer();
    container.RegisterInstance<IRepository1>(repMock.Object);

    var sut = container.Resolve<SomeClass>();
    // The rest of the test...
}

转载注明原文:c# – 使用Moq和Unity进行单元测试的Mock仓库对象的正确方法 - 代码日志