自动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“,记住我!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值