C#单元测试:如何Mock或设置只读属性CarTypes?
解决方案
你的CarTypes属性只有get访问器,没有set,所以直接赋值cars.CarTypes = ...肯定行不通,给你几个可行的处理办法:
方法一:修改原类(最直接)
给CarTypes属性添加protected或internal的set访问器,让测试代码能间接设置它:
public IList<NameValuePair<CarTemplateType>> CarTypes { get { if (m_tempCars == null) { // somelogic } return m_tempCars; } protected set // 或者用 internal set { m_tempCars = value; } }
如果用internal,记得在CarsVM所在项目的AssemblyInfo.cs里添加一行,让测试项目能访问内部成员:
[assembly: InternalsVisibleTo("你的测试项目名称")]
之后测试代码里就能直接赋值了:
cars.CarTypes = new List<NameValuePair<CarTemplateType>> { // 这里填你的测试数据 };
方法二:用反射设置私有字段
不想修改原类的话,直接通过反射给私有字段m_tempCars赋值——毕竟CarTypes的get方法最终返回的就是这个字段:
// 先准备好测试用的数据源 var testCarTypes = new List<NameValuePair<CarTemplateType>> { new NameValuePair<CarTemplateType> { // 初始化你的测试项 } }; // 获取私有字段 var field = typeof(CarsVM).GetField("m_tempCars", BindingFlags.NonPublic | BindingFlags.Instance); // 给字段赋值 field.SetValue(cars, testCarTypes);
这样调用cars.CarTypes时,返回的就是你预设的测试数据。
方法三:用Mock框架(需调整原类)
如果用Moq这类Mock框架,得先把CarTypes改成虚属性,或者把该属性抽象到接口中让CarsVM实现:
比如把属性改成虚的:
public virtual IList<NameValuePair<CarTemplateType>> CarTypes { get { /* 原逻辑不变 */ } }
然后测试里用Moq创建Mock对象:
var mockCarsVM = new Mock<CarsVM>(); var testCarTypes = new List<NameValuePair<CarTemplateType>> { // 填测试数据 }; mockCarsVM.SetupGet(x => x.CarTypes).Returns(testCarTypes); // 使用mock.Object获取实例 var cars = mockCarsVM.Object;
这种方法适合允许调整原类结构的场景,能避免测试代码直接依赖具体实现细节。
内容的提问来源于stack exchange,提问作者4est
相关产品推荐
相关产品推荐

