使用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
相关产品推荐
相关产品推荐

