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

使用Moq时VerifySet报错:预期调用1次实际0次问题求助

Moq.MockException:预期调用1次实际0次的排查方案

1. 核心问题:Vector对象的相等性匹配

Moq默认使用引用相等判定参数是否匹配。如果你的Vector是自定义类且未重写Equals和GetHashCode,哪怕两个实例的X、Y值都是(5,8),也会因为是不同的引用被判定为不匹配,导致验证失败。

解决方式:

  • 重写Vector的相等性方法,让数值相同的实例被判定为相等:
public class Vector
{
    public int X { get; set; }
    public int Y { get; set; }

    public Vector(int x, int y) { X = x; Y = y; }

    public override bool Equals(object obj)
    {
        return obj is Vector vec && X == vec.X && Y == vec.Y;
    }

    public override int GetHashCode()
    {
        return HashCode.Combine(X, Y);
    }
}
  • 或者在验证时使用条件匹配,跳过引用相等检查:
mock.VerifySet(m => m.Position = It.Is<Vector>(v => v.X == 5 && v.Y == 8), Times.Once);

2. 验证语法是否正确

Moq验证属性赋值需要使用专门的VerifySet方法,而非普通的Verify。用错方法会导致匹配逻辑失效:

错误写法:

mock.Verify(m => m.Position = new Vector(5,8), Times.Once);

正确写法:

mock.VerifySet(m => m.Position = new Vector(5,8), Times.Once);

3. 确认Mock实例的注入有效性

检查被测类是否真正使用了你创建的Mock实例,而非内部新建了IMove的其他实现。例如:

// 被测类
public class Player
{
    private readonly IMove _move;
    public Player(IMove move) => _move = move;

    public void MoveTo(int x, int y)
    {
        _move.Position = new Vector(x, y);
    }
}

// 测试代码
[Test]
public void MoveTo_ShouldSetPosition()
{
    var mockMove = new Mock<IMove>();
    var player = new Player(mockMove.Object); // 确保注入的是同一个Mock实例

    player.MoveTo(5,8);

    mockMove.VerifySet(m => m.Position = It.Is<Vector>(v => v.X ==5 && v.Y ==8), Times.Once);
}

4. 检查Mock的行为模式

如果Mock被设置为Strict模式,且未配置Position属性的setter行为,赋值操作会被拦截,无法被记录。建议使用默认的Loose模式,或显式允许属性设置:

var mockMove = new Mock<IMove>(MockBehavior.Loose);
// 或显式开启属性设置的记录
mockMove.SetupProperty(m => m.Position);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 15:08:21