如何在Mock单元测试中为类属性设置默认值?解决报错问题
问题分析与解决方案
报错原因
你遇到的错误本质有两点:
- 目标成员
myflag是字段而非属性,Moq的SetupSet方法仅用于配置属性的setter,不支持字段操作。 - 即使是属性,Moq也只能mock
virtual(虚)、抽象或接口成员——因为Moq通过生成继承类实现mock,非虚成员无法被重写,代理工厂无法处理。
解决方案
方案一:修改原类(推荐,符合面向设计原则)
将字段改为虚属性,让Moq可以正常创建mock:
public class MyClass { public virtual bool MyFlag { get; set; } public virtual bool Detail { get; set; } }
测试代码直接设置属性默认返回值:
[TestMethod()] public async Task Demotest() { var mock = new Mock<MyClass>(); // 配置属性默认返回true mock.Setup(m => m.MyFlag).Returns(true); mock.Setup(m => m.Detail).Returns(true); MyClass testObj = mock.Object; Assert.IsTrue(testObj.MyFlag); Assert.IsTrue(testObj.Detail); }
方案二:无法修改原类时的替代方案
如果不能改动MyClass的代码,无需使用Moq,直接通过反射设置字段值即可:
[TestMethod()] public async Task Demotest() { MyClass testObj = new MyClass(); // 设置myflag字段为true var myFlagField = typeof(MyClass).GetField("myflag", BindingFlags.Public | BindingFlags.Instance); myFlagField?.SetValue(testObj, true); // 设置detail字段为true var detailField = typeof(MyClass).GetField("detail", BindingFlags.Public | BindingFlags.Instance); detailField?.SetValue(testObj, true); // 验证结果 Assert.IsTrue((bool)myFlagField.GetValue(testObj)); Assert.IsTrue((bool)detailField.GetValue(testObj)); }
如果字段是私有类型,将BindingFlags.Public替换为BindingFlags.NonPublic即可。
内容的提问来源于stack exchange,提问作者Neo
相关产品推荐
相关产品推荐

