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

不可修改原类时,如何Mock非接口/非虚方法并设置返回值?

问题

如何对非接口、非虚方法的类执行Mock的Setup(...)和Returns(...)操作?约束条件:无法将目标类转为接口、无法将方法改为虚方法,且不可修改原类及方法,请求提供生成假数据的可行方案建议。

相关代码

public class Product
{
    public int Sum(int a, int b) => a + b;
}

[TestMethod]
public void SumTest()
{
    var moc = new Mock<Product>();
    moc.Setup(m => m.Sum(1, 1)).Returns(3);
}
可行方案建议
  • 使用商业隔离框架
    像TypeMock Isolator、JustMock这类框架,能绕过.NET的访问限制,直接Mock非虚、非接口方法,无需修改原代码。以JustMock为例:

    [TestMethod]
    public void SumTest()
    {
        var mock = Mock.Create<Product>();
        Mock.Arrange(() => mock.Sum(1, 1)).Returns(3);
        
        int result = mock.Sum(1, 1);
        Assert.AreEqual(3, result);
    }
    

    这类框架靠IL编织技术拦截方法调用,不过大多是商业付费软件。

  • 用适配器模式创建包装类
    不修改原类的前提下,给原类做一层包装,定义可Mock的接口,把原类的调用封装进去。示例:

    // 定义包装接口
    public interface IProductWrapper
    {
        int Sum(int a, int b);
    }
    
    // 包装类,调用原Product的方法
    public class ProductWrapper : IProductWrapper
    {
        private readonly Product _product;
        public ProductWrapper(Product product)
        {
            _product = product;
        }
        
        public int Sum(int a, int b)
        {
            return _product.Sum(a, b);
        }
    }
    
    // 测试代码
    [TestMethod]
    public void SumTest()
    {
        var mockWrapper = new Mock<IProductWrapper>();
        mockWrapper.Setup(m => m.Sum(1, 1)).Returns(3);
        
        int result = mockWrapper.Object.Sum(1, 1);
        Assert.AreEqual(3, result);
    }
    

    这种方式属于常规架构适配,完全免费,也符合代码设计原则。

  • 反射+IL注入替换方法实现(临时方案)
    通过反射结合IL注入库(如Harmony)修改原方法的实现逻辑,替换成自定义的假数据逻辑。示例思路:

    // 初始化Harmony实例
    var harmony = new Harmony("test.product.sum.patch");
    // 获取原方法的MethodInfo
    MethodInfo sumMethod = typeof(Product).GetMethod("Sum", BindingFlags.Public | BindingFlags.Instance);
    // 替换方法实现
    harmony.Patch(sumMethod, postfix: new HarmonyMethod(typeof(SumPatch).GetMethod("OverrideSumResult")));
    
    // 自定义替换逻辑类
    public static class SumPatch
    {
        public static void OverrideSumResult(int a, int b, ref int __result)
        {
            // 当参数为1和1时,强制返回3
            if (a == 1 && b == 1)
            {
                __result = 3;
            }
        }
    }
    

    这种方式复杂度高,容易污染测试环境,仅适合临时应急使用,测试后要注意清理注入的代码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 12:53:22