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容器。我建议你多读一些关于测试的书,比如这本书。你是对的,我确实感觉到了服务类的设计问题。