Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ruby-on-rails-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unit testing 使用多个构造函数参数模拟和测试类_Unit Testing_Nunit_Mocking_Moq - Fatal编程技术网

Unit testing 使用多个构造函数参数模拟和测试类

Unit testing 使用多个构造函数参数模拟和测试类,unit-testing,nunit,mocking,moq,Unit Testing,Nunit,Mocking,Moq,我的服务层类是为构造函数注入而设置的。在模拟和测试这些类时,如何避免为测试中不使用的参数传入null 我试图避免的示例代码: [TestFixture] public class SomeServicesTests { SomeServices _someServices; [SetUp] public void Initialize() { _someServices= new SomeServices (null,

我的服务层类是为构造函数注入而设置的。在模拟和测试这些类时,如何避免为测试中不使用的参数传入
null

我试图避免的示例代码:

[TestFixture]
public class SomeServicesTests
{
    SomeServices _someServices;

    [SetUp]
    public void Initialize()
    {
        _someServices= new SomeServices (null, 
                                        new StubRepositoryOne(), 
                                        null, 
                                        null, 
                                        new StubRepositoryTwo(), 
                                        null, 
                                        null, 
                                        null,
                                        null);

    }

    [Test]
    public void Test_Something()
    {
        string input = "yes";
        string exptectedOutput = "no";

        string output = _someServices.SomeFunction(input); // uses StubRepositoryOne and StubRepositoryTwo
        Assert.AreEqual(exptectedOutput, output);
    }
}

我通常验证注入的参数与null。我通常只是路过

new Mock<T>().Object
新建Mock().Object

对于这些。

存根所有缺少的参数,并始终检查SomeService中的空参数。每次使用时检查输入是否为null都很麻烦。因此,最好总是在构造函数中检查null,并抛出ArgumentNullException


您提到一些输入参数是私有的。它们必须被提取出来,你的注射模式才能工作。

在我的答案被接受后添加,但是

测试只需要传递一些依赖项,这一事实表明可能存在设计问题。一个很好的试金石测试是,一个类型中的所有字段都应该在每个方法中使用——始终这样做非常困难——但如果不能,则意味着该类可能可以被划分为更小的类,并承担更精细的职责。当您分解它们时,每个类将只获取它们立即需要的依赖项

另一方面,如果你在这里做的是一个手工滚动的服务定位器,你只测试一个功能子集,你可能想考虑创建只测试构造函数。例如:

internal SomeServices(IServiceOne one, IServiceTwo two)
{
}
或者使用getter/setter公开服务并相应地分配。同样,此处的内部关键字可用于保持设计意图的整洁:

public IServiceOne One
{
   get { return _one; }
   internal set { _one = value; }
}

当然,,您希望将InternalsVisibleTo属性添加到您的代码中,以允许您的测试访问这些内部方法。

但是如果它们在
SomeServices
中都是私有的,那么如何传入
StubRepositoryOne
StubRepositoryTwo
?@Omar-我将使用公共接口作为依赖项,而不是私有类。存根是。。。类实际上是存根?如果是这样,并且您正在使用Moq(正如您的标记所暗示的),那么让Moq动态地创建接口的存根(如我上面所示-用您的接口替换T)。因此,没有办法让Moq创建我的服务类,stubing除了我指定的那些参数之外的所有参数
StubRepositoryOne/StubRepositoryTwo
?@Omar-您不希望Moq在测试中创建您的类。您希望测试的是一个实际实例,而不是模拟/伪造/存根。Moq创建了虚假的依赖关系。它是一个隔离/模拟框架,而不是IoC容器。我建议你多读一些关于测试的书,比如这本书。你是对的,我确实感觉到了服务类的设计问题。