如何Mock参数为异步函数的服务依赖?附代码示例
如何Mock参数为Func<CancellationToken, IServiceProvider, Task>的QueueBackgroundWorkItem方法
你要Mock的QueueBackgroundWorkItem方法接收一个Func<CancellationToken, IServiceProvider, Task>类型的委托参数,结合Moq框架,这里提供几种实用的处理方式:
1. 匹配任意委托参数(基础用法)
如果只需要验证方法被调用过,不需要关心具体传入的委托逻辑,可以直接用It.IsAny<>匹配任意符合类型的参数:
Mock<IBackgroundTaskQueue> _mock = new Mock<IBackgroundTaskQueue>(); // Setup void方法,无需返回值(原方法是void,不要加Returns(Task.CompletedTask)) _mock.Setup(x => x.QueueBackgroundWorkItem(It.IsAny<Func<CancellationToken, IServiceProvider, Task>>())) .Verifiable(); // 执行被测试代码后,验证方法是否被调用 _mock.Verify(x => x.QueueBackgroundWorkItem(It.IsAny<Func<CancellationToken, IServiceProvider, Task>>()), Times.Once);
2. 捕获传入的委托并执行(验证委托逻辑)
如果需要验证传入的委托逻辑是否正确,或者要手动执行委托来测试其行为,可以通过Callback捕获传入的委托:
Mock<IBackgroundTaskQueue> _mock = new Mock<IBackgroundTaskQueue>(); Func<CancellationToken, IServiceProvider, Task> capturedWorkItem = null; // 捕获传入的委托 _mock.Setup(x => x.QueueBackgroundWorkItem(It.IsAny<Func<CancellationToken, IServiceProvider, Task>>())) .Callback<Func<CancellationToken, IServiceProvider, Task>>(workItem => { capturedWorkItem = workItem; }); // 执行被测试代码,触发QueueBackgroundWorkItem调用 // 手动执行捕获到的委托,传入模拟的依赖 var mockServiceProvider = new Mock<IServiceProvider>().Object; var cancellationToken = CancellationToken.None; await capturedWorkItem(cancellationToken, mockServiceProvider); // 验证方法调用次数 _mock.Verify(x => x.QueueBackgroundWorkItem(It.IsAny<Func<CancellationToken, IServiceProvider, Task>>()), Times.Once);
3. 匹配特定委托(自定义判断逻辑)
如果需要仅匹配满足特定条件的委托,可以用It.Is<>()添加自定义校验逻辑:
Mock<IBackgroundTaskQueue> _mock = new Mock<IBackgroundTaskQueue>(); _mock.Setup(x => x.QueueBackgroundWorkItem(It.Is<Func<CancellationToken, IServiceProvider, Task>>(func => { // 这里添加自定义判断逻辑,比如验证委托是否依赖某个特定服务 // 示例:假设委托需要从IServiceProvider获取ILogger服务 var testProvider = new Mock<IServiceProvider>().Object; try { // 尝试执行委托的部分逻辑来判断 var task = func(CancellationToken.None, testProvider); return task != null; } catch { return false; } }))) .Verifiable();
注意:原方法QueueBackgroundWorkItem是void类型,不要调用.Returns(Task.CompletedTask),Moq中Setup void方法不需要设置返回值。
内容的提问来源于stack exchange,提问作者M Javad Salehi
相关产品推荐
相关产品推荐

