我正在尝试为具有以下构造函数定义的 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/