问题
由于依赖注入,特别是构造函数注入的广泛使用,使得编写单元测试时,需要使用Mock框架(例如Moq
)生成测试类的依赖接口的"模拟"实现,并验证接口是否按预期使用。
例如eShopOnContainers中的测试代码就使用了Moq
,实现如下:
private readonly Mock<IMediator> _mediatorMock;
private readonly Mock<IOrderQueries> _orderQueriesMock;
private readonly Mock<IIdentityService> _identityServiceMock;
private readonly Mock<ILogger<OrdersController>> _loggerMock;public OrdersWebApiTest()
{_mediatorMock = new Mock<IMediator>();_orderQueriesMock = new Mock<IOrderQueries>();_identityServiceMock = new Mock<IIdentityService>();_loggerMock = new Mock<ILogger<OrdersController>>();
}[Fact]
public async Task Cancel_order_with_requestId_success()
{//Arrange_mediatorMock.Setup(x => x.Send(It.IsAny<IdentifiedCommand<CancelOrderCommand, bool>>(), default(CancellationToken))).Returns(Task.FromResult(true));//Actvar orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object);var actionResult = await orderController.CancelOrderAsync(new CancelOrderCommand(1), Guid.NewGuid().ToString()) as OkResult;//AssertAssert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.OK);}
可以看到OrdersController
依赖了4个接口,而每个测试用例都必须将Mock对象传入构造函数,一旦更改了OrdersController
的构造函数参数,那么你将需要更改大量单元测试代码。
如何简化这部分工作?
Moq.AutoMocker
Moq.AutoMocker是一款基于Moq的IoC容器,它可以用来自动创建待测试类的依赖。
引用nuget包Moq.AutoMock
之后,上面的测试代码可以修改如下:
[Fact]
public async Task Cancel_order_with_requestId_success()
{//Arrangevar autoMocker = new AutoMocker();var orderController = autoMocker.CreateInstance<OrdersController>();var mediatorMock = autoMocker.GetMock<IMediator>();mediatorMock.Setup(x => x.Send(It.IsAny<IdentifiedCommand<CancelOrderCommand, bool>>(), default(CancellationToken))).Returns(Task.FromResult(true));//Actvar actionResult = await orderController.CancelOrderAsync(new CancelOrderCommand(1), Guid.NewGuid().ToString()) as OkResult;//AssertAssert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.OK);
}
可以看到,无需提前生成Mock对象,autoMocker.CreateInstance<T>
即可创建指定类型的实例。autoMocker.GetMock<T>
可以获得依赖接口的Mock实例,然后像以前一样,执行Setup
或Verify
方法。
结论
Moq.AutoMocker大大减少了在单位测试中编写重复Mock代码的数量,简化了待测试类的生成。
如果你使用Moq,我强烈推荐它。
如果你觉得这篇文章对你有所启发,请关注我的个人公众号”My IO“,记住我!