使用IoC时,单元测试的策略应该是什么?

Tom*_*ana 16 c# unit-testing dependency-injection castle-windsor inversion-of-control

毕竟我读到的关于依赖注入和IoC的内容我决定尝试在我们的应用程序中使用Windsor Container(它是一个50K LOC多层Web应用程序,所以我希望它不是一个矫枉过正).我使用了一个简单的静态类来包装容器,并在启动应用程序时对其进行初始化,这对于现在来说非常好.

我的问题是关于单元测试.我知道通过让我可以将类协作者的存根/模拟实现注入到被测试的类中,DI将使我的生活变得更加轻松.我已经使用这种技术编写了几个测试,这似乎对我有意义.我不确定的是我是否应该在单元测试中使用IoC(在本例中为Windsor Castle)(可能以某种方式将其配置为针对我的特殊情况返回存根/模拟)或者是否更好地连接所有依赖项在测试中手动.你怎么想,什么做法对你有用?

Dar*_*rov 20

在单元测试中不需要DI容器,因为依赖关系是通过使用Rhino MocksMoq等框架生成的模拟对象提供的.因此,例如,当您测试一个依赖于某个接口的类时,通常通过构造函数注入来提供此依赖项.

public class SomeClassToTest
{
    private readonly ISomeDependentObject _dep;
    public SomeClassToTest(ISomeDependentObject dep)
    {
        _dep = dep;
    }

    public int SomeMethodToTest()
    {
        return _dep.Method1() + _dep.Method2();
    }
}
Run Code Online (Sandbox Code Playgroud)

在您的应用程序中,您将使用DI框架ISomeDependentObject在构造函数中传递一些实际的实现,这些实现本身可能依赖于其他对象,而在单元测试中您创建一个模拟对象,因为您只想隔离地测试此类.Rhino Mocks示例:

[TestMethod]
public void SomeClassToTest_SomeMethodToTest()
{
    // arrange
    var depStub = MockRepository.CreateStub<ISomeDependentObject>();
    var sut = new SomeClassToTest(depStub);
    depStub.Stub(x => x.Method1()).Return(1);
    depStub.Stub(x => x.Method2()).Return(2);

    // act
    var actual = sut.SomeMethodToTest();

    // assert
    Assert.AreEqual(3, actual);
}
Run Code Online (Sandbox Code Playgroud)