如何在没有IoC容器的情况下对您的控制器进行单元测试?

6 asp.net-mvc unit-testing controller ioc-container inversion-of-control

在构建我最新的ASP.NET MVC项目时,我开始进入单元测试,依赖注入和所有爵士乐.

我现在想要单元测试我的控制器,我很难搞清楚如何在没有IoC容器的情况下正确地执行此操作.

以一个简单的控制器为例:

public class QuestionsController : ControllerBase
{
    private IQuestionsRepository _repository = new SqlQuestionsRepository();

    // ... Continue with various controller actions
}
Run Code Online (Sandbox Code Playgroud)

由于它直接实例化SqlQuestionsRepository,因此该类不是单元可测试的.那么,让我们沿着Dependancy Injection路线行进并做:

public class QuestionsController : ControllerBase
{
    private IQuestionsRepository _repository;

    public QuestionsController(IQuestionsRepository repository)
    {
        _repository = repository;
    }
}
Run Code Online (Sandbox Code Playgroud)

这似乎更好.我现在可以使用模拟IQuestionsRepository轻松编写单元测试.但是,现在要实例化控制器的是什么?在调用链SqlQuestionRepository的某个地方必须进行实例化.似乎我只是简单地将问题转移到别处,而不是摆脱它.

现在,我知道这是一个很好的例子,IoC容器可以通过为我配置控制器依赖性来帮助您,同时保持我的控制器易于单元测试.

我的问题是,如何在没有 IoC容器的情况下对这种性质的东西进行单元测试?

注意:我不反对IoC容器,我很快就会走这条路.但是,我很好奇对于那些不使用它们的人来说,替代方案是什么.

Pet*_*ter 2

是否可以保留字段的直接实例化并提供设置器?在这种情况下,您只会在单元测试期间调用设置器。像这样的东西:

public class QuestionsController : ControllerBase
{
    private IQuestionsRepository _repository = new SqlQuestionsRepository();

    // Really only called during unit testing...
    public QuestionsController(IQuestionsRepository repository)
    {
        _repository = repository;
    }
}
Run Code Online (Sandbox Code Playgroud)

我对 .NET 不太熟悉,但顺便说一句,在 Java 中,这是重构现有代码以提高可测试性的常见方法。IE,如果您有已在使用的类并且需要修改它们以提高代码覆盖率而不破坏现有功能。

我们团队以前就这样做过,通常我们将setter的可见性设置为package-private,并保持测试类的包相同,以便它可以调用setter。