为何无法修改未设置的MOQ模拟对象属性值?
问题原因及解决办法
Moq创建的模拟对象默认不会自动跟踪可读写属性的赋值操作。当你只通过Setup(x => x.FirstInput).Returns(1)配置了FirstInput的返回值,但未对SecondInput做任何配置时,即使业务代码里给userInput.SecondInput赋值,Moq也不会保存这个赋值结果——它会默认返回属性类型的默认值(比如int类型的0),这就是你断言失败的原因。
要解决这个问题,有两种常用方式:
1. 启用所有属性的自动跟踪
使用Moq的SetupAllProperties()方法,让模拟对象像真实对象一样处理所有可读写属性的get和set操作,自动跟踪属性值的变化:
// 创建模拟对象并启用属性跟踪 var mockUserInput = new Mock<IUserInput>(); mockUserInput.SetupAllProperties(); // 设置FirstInput的初始值 mockUserInput.Object.FirstInput = 1; var calculator = new CalculatorCore(mockUserInput.Object); var result = calculator.AddByUserInput(); // 此时可以正确获取修改后的SecondInput值 Assert.Equal(你期望的数值, mockUserInput.Object.SecondInput);
2. 单独配置目标属性的读写行为
如果你只需要跟踪特定属性(比如这里的SecondInput),可以单独用SetupProperty()方法配置:
var mockUserInput = new Mock<IUserInput>(); // 设置FirstInput的返回值 mockUserInput.Setup(x => x.FirstInput).Returns(1); // 配置SecondInput为可设置的属性,初始值设为0 mockUserInput.SetupProperty(x => x.SecondInput, 0); var calculator = new CalculatorCore(mockUserInput.Object); var result = calculator.AddByUserInput(); Assert.Equal(你期望的数值, mockUserInput.Object.SecondInput);
你也可以手动用SetupSet和SetupGet结合回调来跟踪属性值:
int storedSecondInput = 0; var mockUserInput = new Mock<IUserInput>(); mockUserInput.Setup(x => x.FirstInput).Returns(1); // 监听SecondInput的赋值操作,把值存到变量里 mockUserInput.SetupSet(x => x.SecondInput = It.IsAny<int>()) .Callback<int>(value => storedSecondInput = value); // 读取SecondInput时返回存储的变量值 mockUserInput.SetupGet(x => x.SecondInput) .Returns(() => storedSecondInput); var calculator = new CalculatorCore(mockUserInput.Object); var result = calculator.AddByUserInput(); Assert.Equal(你期望的数值, storedSecondInput);
内容的提问来源于stack exchange,提问作者Harutyun Dokhoyan
相关产品推荐
相关产品推荐

