自动Mock,让编写单元测试更简单

问题

由于依赖注入,特别是构造函数注入的广泛使用,使得编写单元测试时,需要使用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));

    //Act
    var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object);
    var actionResult = await orderController.CancelOrderAsync(new CancelOrderCommand(1), Guid.NewGuid().ToString()) as OkResult;

    //Assert
    Assert.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()
{
    //Arrange
    var 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));

    //Act
    var actionResult = await orderController.CancelOrderAsync(new CancelOrderCommand(1), Guid.NewGuid().ToString()) as OkResult;

    //Assert
    Assert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.OK);
}

可以看到,无需提前生成Mock对象,autoMocker.CreateInstance<T>即可创建指定类型的实例。autoMocker.GetMock<T>可以获得依赖接口的Mock实例,然后像以前一样,执行SetupVerify方法。

结论

Moq.AutoMocker大大减少了在单位测试中编写重复Mock代码的数量,简化了待测试类的生成。

如果你使用Moq,我强烈推荐它。

如果你觉得这篇文章对你有所启发,请关注我的个人公众号”My IO“,记住我!

自动Mock,让编写单元测试更简单》来自互联网,仅为收藏学习,如侵权请联系删除。本文URL:http://www.hashtobe.com/1178.html