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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 20:51:01