正确的方法来模拟使用起订量和单位单元测试库对象 [英] Proper way to Mock repository objects for unit tests using Moq and Unity

查看:169
本文介绍了正确的方法来模拟使用起订量和单位单元测试库对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的工作,我们所使用的起订量嘲讽和Unity为IOC容器。我是相当新的这一点,不必在工作的许多资源来帮助我确定我应该使用的最佳实践。

At my job we are using Moq for mocking and Unity for an IOC container. I am fairly new to this and do not have many resources at work to help me out with determining the best practices I should use.

现在,我有一组库接口。(例如:IRepository1,IRepository2 ...... IRepository4)一个特定进程中需要使用做的工作。

Right now, I have a group of repository interfaces (Ex: IRepository1, IRepository2... IRepository4) that a particular process needs to use to do its job.

在实际的代码我能确定所有的通过IOC容器和使用RegisterType()方法IRepository对象。

In the actual code I can determine all of the IRepository objects by using the IOC container and using the RegisterType() method.

我试图找出最好的办法是能够测试需要4提到库的方式。

I am trying to figure out the best way to be able to test the method that needs the 4 mentioned repositories.

我想我可以只登记统一IOC容器的一个新实例,并调用RegisterInstance在容器上在Mock.Object值传递的每一个每一个模仿对象。我努力使这一注册过程可重复使用的,所以我没有跟上每个单元测试一遍又一遍地做同样的事情,除非一个单元测试,需要一些特定的数据来自于库回来。这就是问题的所在......什么是在嘲笑库设置的预期值的最佳做法?好像如果我只是叫RegisterType统一的容器,我将失去实际模拟对象的引用,将无法覆盖的行为上。

I was thinking I could just register a new instance of the Unity IOC container and call RegisterInstance on the container for each mock object passing in the Mock.Object value for each one. I am trying to make this registration process reusable so I do not have to keep doing the same thing over and over with each unit test unless a unit test requires some specific data to come back from the repository. This is where the problem lies... what is the best practice for setting up expected values on a mocked repository? It seems like if I just call RegisterType on the Unity container that I would lose a reference to the actual Mock object and would not be able to override behavior.

推荐答案

单元测试不应该使用的容器。依赖注入(DI)有两个阶段:

Unit tests should not use the container at all. Dependency Injection (DI) comes in two phases:


  1. 使用DI模式来注入依赖成为消费者。你并不需要一个容器来做到这一点。

  2. 在应用程序的成分根,使用DI容器(或穷人的DI)为所有的组件装配起来。

  1. Use DI patterns to inject dependencies into consumers. You don't need a container to do that.
  2. At the application's Composition Root, use a DI Container (or Poor Man's DI) to wire all components together.

如何不使用任何DI容器在所有的单元测试

作为一个例子,考虑使用IRepository1一类。通过使用构造器注入的模式,我们可以依赖的类的不变。

As an example, consider a class that uses IRepository1. By using the Constructor Injection pattern, we can make the dependency an invariant of the class.

public class SomeClass
{
    private readonly IRepository1 repository;

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

        this.repository = repository;
    }

    // More members...
}

注意,只读关键字与卫兵子句结合保证了字段不为空,如果实例成功实例。

Notice that the readonly keyword combined with the Guard Clause guarantees that the repository field isn't null if the instance was successfully instantiated.

您不需要一个容器MyClass的创建一个新的实例。

You don't need a container to create a new instance of MyClass. You can do that directly from a unit test using Moq or another Test Double:

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

请参阅< A HREF =htt​​p://stackoverflow.com/questions/1465849/using-ioc-for-unittesting/1465896#1465896>这里更多信息...

See here for more information...

如何使用统一的单元测试

不过,如果你绝对必须在测试中使用的统一,你可以创建容器和使用RegisterInstance方式:

However, if you absolutely must use Unity in your tests, you can create the container and use the RegisterInstance method:

[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...
}

这篇关于正确的方法来模拟使用起订量和单位单元测试库对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆