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

已实现FakeItEasy公共虚拟方法模拟,求指导模拟私有方法

嘿,得先给你划个重点:FakeItEasy 从设计初衷就不支持直接模拟私有方法——它的核心是帮你隔离公共/可重写的成员,私有方法属于类的内部实现细节,本来就不该直接被测试或模拟。不过咱们有两种可行的思路来解决你的问题,下面给你详细说:

方案1:重构代码(推荐,符合测试最佳实践)

最稳妥的方式是把私有方法里的核心逻辑抽成独立的可注入依赖,这样就能用FakeItEasy轻松模拟这个依赖的行为,间接实现对原私有逻辑的控制。

步骤1:定义处理核心逻辑的接口

把AddIntegers里的计算逻辑抽成一个接口:

public interface IIntegerCalculator
{
    int CalculateValue();
}

步骤2:实现接口的真实逻辑

把原私有方法里的计算逻辑移到这个实现类里:

public class IntegerCalculator : IIntegerCalculator
{
    public int CalculateValue()
    {
        int i = 3;
        int j = i * 100;
        int k = j * 30 / 100;
        return k;
    }
}

步骤3:改造原XYZ类

通过构造函数注入上面的依赖,替换原私有方法的逻辑:

public class XYZ
{
    public static int nValue = 0;
    private readonly IIntegerCalculator _calculator;

    // 构造函数注入依赖
    public XYZ(IIntegerCalculator calculator)
    {
        _calculator = calculator;
    }

    // 假设原来有个公共方法触发私有逻辑,这里改成调用依赖
    public void RunCalculation()
    {
        int k = _calculator.CalculateValue();
        Show(string.Format("Value Here {0}", k.ToString()));
        nValue = k;
    }

    public virtual void Show(string message)
    {
        // 原方法实现
    }
}

步骤4:编写测试用例

现在就可以用FakeItEasy模拟依赖,控制计算结果,验证整个流程:

[Test]
public void RunCalculation_ShouldSetCorrectNValue_WithMockedCalculator()
{
    // 模拟计算器依赖,指定返回值
    var mockCalculator = A.Fake<IIntegerCalculator>();
    A.CallTo(() => mockCalculator.CalculateValue()).Returns(90);

    // 创建XYZ实例,注入模拟依赖
    var xyz = new XYZ(mockCalculator);
    // 模拟Show方法(因为它是虚拟的)
    A.CallTo(() => xyz.Show(A<string>._)).DoesNothing();

    // 执行测试方法
    xyz.RunCalculation();

    // 验证结果
    Assert.AreEqual(90, XYZ.nValue);
    A.CallTo(() => mockCalculator.CalculateValue()).MustHaveHappenedOnceExactly();
    A.CallTo(() => xyz.Show("Value Here 90")).MustHaveHappenedOnceExactly();
}

方案2:反射调用私有方法(仅应急使用)

如果实在没办法重构代码,你可以用.NET的反射机制直接调用私有方法,但这不是模拟私有方法,而是直接执行它的真实逻辑,只能用来验证结果,没法修改它的行为:

[Test]
public void AddIntegers_ShouldSetNValue_Correctly()
{
    var xyz = new XYZ();
    // 通过反射获取私有方法
    var addMethod = typeof(XYZ).GetMethod(
        "AddIntegers", 
        System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance
    );
    // 模拟Show方法
    A.CallTo(() => xyz.Show(A<string>._)).DoesNothing();

    // 调用私有方法
    addMethod.Invoke(xyz, null);

    // 验证静态字段的值
    Assert.AreEqual(90, XYZ.nValue);
    A.CallTo(() => xyz.Show("Value Here 90")).MustHaveHappenedOnceExactly();
}

⚠️ 注意:这种方式是绕过封装直接操作内部逻辑,会让测试和实现细节绑定得很紧,后续代码改动很容易导致测试失败,所以非必要别用。

内容的提问来源于stack exchange,提问作者Sujeet Singh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 02:32:52