c# - 是否有必要模拟单元测试中的所有依赖项?

标签 c# .net unit-testing mocking

我正在尝试为具有以下构造函数定义的 ASP.NET 创建单元测试(在运行实际应用程序时填充了 Ninject):

    public OrderController(IViewModelFactory modelFactory, INewsRepository repository, ILoggedUserHelper loggedUserHelper,
        IDelegateHelper delegateHelper, ICustomerContextWrapper customerContext) {
        this.factory = modelFactory;
        this.loggedUserHelper = loggedUserHelper;
        this.delegateHelper = delegateHelper;
        this.customerContext = customerContext;
    }

我想测试 OrderController 类中的方法,但为了隔离它,我必须模拟所有这些依赖项,这变得非常荒谬(可能还必须模拟子依赖项).

在这种情况下,对此类进行单元测试的最佳做法是什么?

最佳答案

好吧,您必须为所有依赖项提供测试替身,不一定是模拟。

幸运的是,现在是 21 世纪,有一些工具可以让我们的工作变得更轻松。您可以使用 AutoFixture创建 OrderController 实例并根据需要注入(inject)模拟。

var fixture = new Fixture().Customize(new AutoConfiguredMoqCustomization());
var orderController = fixture.Create<OrderController>();

这基本上等同于:

var factory = new Mock<IViewModelFactory>();
var repository = new Mock<INewsRepository>();
var delegateHelper = new Mock<IDelegateHelper >();
var customerContext = new Mock<ICustomerContextWrapper >();

var orderController = new OrderController(factory.Object, repository.Object, delegateHelper.Object, customerContext.Object);

如果这些依赖依赖于其他类型,那么它们也会被设置。具有 AutoConfiguredMoqCustomization 自定义功能的 AutoFixture 将构建完整的依赖关系图。

如果您需要访问存储库 mock,以便稍后可以对其进行一些额外的设置或断言,您可以卡住它。卡住一个类型将使 fixture 容器只包含该类型的一个实例,例如:

var fixture = new Fixture().Customize(new AutoConfiguredMoqCustomization());
var repositoryMock = fixture.Freeze<Mock<INewsRepository>>();
repositoryMock.Setup(x => x.Retrieve()).Returns(1);

//the frozen instance will be injected here
var orderController = fixture.Create<OrderController>(); 

repositoryMock.Verify(x => x.Retrieve(), Times.Once);

我在这些示例中使用了 Moq,但 AutoFixture 还集成了 NSubstitute、RhinoMock 和 Foq。

披露:我是该项目的贡献者之一

关于c# - 是否有必要模拟单元测试中的所有依赖项?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27104076/

相关文章:

c# - WinForms WebBrowser 中的拼写检查

jquery - 在移动 View 中显示小部件演示

c# - 使用 ajax 将 Knockout.js View 模型发布到 ASP.NET MVC Controller 操作会导致空值

c# - 为什么我的 Storboard 不显示?

c# - C++/命令行界面 : Implementing an abstract C# class that implements INotifyPropertyChanged results in C++ compiler error C3766

php - PHPUnit 是否有一些内置的递归数组比较功能?

c# - 使用 Autofac 对委托(delegate)工厂进行单元测试

unit-testing - 白盒测试用例,代码覆盖率100%

c# - 如何获取exe的嵌入式资源的文件名?

c# - 当外部库不向后兼容时检查属性是否存在