You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何验证包含子Mock的Moq对象无其他调用?

Moq验证父Mock时意外触发子Mock未验证调用的问题

问题场景

以下测试代码执行后会失败:

[Test]
public void Test()
{
    var mockGetter = new Mock<IHostedServiceGetter>();
    var mockService = new Mock<IHostedService>();

    mockGetter.Setup(i => i.Get()).Returns(mockService.Object);

    mockGetter.Object.Get();
    mockService.Object.StartAsync(CancellationToken.None);

    mockGetter.Verify(i => i.Get(), Times.Once);
    mockGetter.VerifyNoOtherCalls();
}

public interface IHostedServiceGetter
{
    public IHostedService Get();
}

抛出的异常信息:

Moq.MockException : Mock<IHostedService:1>:
This mock failed verification due to the following unverified invocations:

   IHostedService.StartAsync(CancellationToken)

移除对mockService.Object.StartAsync()的调用后,测试即可通过。

对比另一个测试(仅返回新创建的Mock对象而非已定义的mockService),则能正常通过:

[Test]
public void Test()
{
    var mockGetter = new Mock<IHostedServiceGetter>();
    var mockService = new Mock<IHostedService>();

    mockGetter.Setup(i => i.Get()).Returns(new Mock<IHostedService>().Object);

    mockGetter.Object.Get();
    mockService.Object.StartAsync(CancellationToken.None);

    mockGetter.Verify(i => i.Get(), Times.Once);
    mockGetter.VerifyNoOtherCalls();
}

编辑补充:将Setup改为延迟返回形式后,测试恢复正常:

mockGetter.Setup(i => i.Get()).Returns(() => mockService.Object);

原因解释

Moq内部有关联Mock跟踪机制:当直接把一个Mock对象(mockService.Object)作为另一个Mock的返回值时,Moq会自动为两个Mock建立关联。调用父Mock的VerifyNoOtherCalls()时,Moq会递归验证所有关联的子Mock是否存在未验证的调用,导致原本仅验证mockGetter的测试,意外触发了mockService的未验证调用检查。

而使用延迟返回(Returns(() => mockService.Object))时,Moq无法在Setup阶段提前捕获到返回的Mock对象,也就不会建立两者的关联,因此验证父Mock时只会检查自身调用,不会涉及子Mock。

第二个测试中返回的是全新的匿名Mock对象,和mockService无任何关联,所以mockService的调用不会影响mockGetter的验证。

解决方法

  • 使用延迟返回的方式提供子Mock对象,即Returns(() => mockService.Object),切断Moq对两个Mock的关联跟踪;
  • 如果不需要验证子Mock的调用,可以显式设置子Mock为宽松模式,比如创建时指定new Mock<IHostedService>(MockBehavior.Loose),宽松模式下Moq默认不会校验未设置的调用;
  • 或者在验证父Mock前,手动清空子Mock的调用记录:mockService.ResetCalls(),避免未验证调用被Moq检测到。

内容的提问来源于stack exchange,提问作者ewok

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 16:25:05