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

NSubstitute是否支持基于真实实例仅Mock部分方法?

嘿,你问的这个需求NSubstitute其实已经内置支持啦!完全不用自己写Wrapper类这么麻烦,它提供了针对真实实例的**部分模拟(Partial Mock)**能力,既能保留原有实例的大部分功能,又能轻松验证特定方法的调用,甚至还能按需替换某些方法的实现。下面给你一步步讲怎么用:

使用NSubstitute实现真实实例的部分Mock

1. 快速创建基于真实实例的Substitute

核心就是用Substitute.For<T>(真实实例)这个方法,把你的真实对象传进去。默认情况下,所有方法都会优先调用真实实例的逻辑,你只需要针对性处理要验证或替换的方法就行。

举个实际的代码例子,假设我们有这样的接口和实现类:

public interface IOrderService {
    void ProcessOrder(int orderId); // 想保留真实逻辑的方法
    string GenerateOrderNumber(string prefix); // 想验证调用的方法
}

public class OrderService : IOrderService {
    public void ProcessOrder(int orderId) {
        // 真实的订单处理逻辑
        Console.WriteLine($"处理订单:{orderId}");
    }

    public string GenerateOrderNumber(string prefix) {
        // 真实的单号生成逻辑
        return $"{prefix}-{Guid.NewGuid().ToString().Substring(0, 8)}";
    }
}

创建部分Mock的实例就这么简单:

// 先初始化真实实例
var realService = new OrderService();
// 基于真实实例创建Substitute
var partialMock = Substitute.For<IOrderService>(realService);

2. 保留原有功能,仅验证方法调用

如果你的需求只是检查某个方法是否以特定参数被调用,不需要修改它的逻辑,那直接用Received()验证就好——因为默认情况下这个方法还是会执行真实逻辑的:

// 调用方法(会走真实的单号生成逻辑)
var orderNumber = partialMock.GenerateOrderNumber("ORD");
Console.WriteLine(orderNumber);

// 验证方法是否被调用过,参数是否正确
partialMock.Received().GenerateOrderNumber("ORD");
// 也可以验证调用次数,比如是否被调用了一次
partialMock.Received(1).GenerateOrderNumber(Arg.Is<string>(x => x.StartsWith("ORD")));

3. 按需替换特定方法的实现

如果某些方法你想临时替换成Mock逻辑,其他方法依然保留真实功能,也很容易做到:

// 替换GenerateOrderNumber的实现,固定返回一个值
partialMock.GenerateOrderNumber(Arg.Any<string>()).Returns("MOCK-123456");

// 调用ProcessOrder,还是执行真实的订单处理逻辑
partialMock.ProcessOrder(1001);
// 调用GenerateOrderNumber,会返回我们Mock的结果
var mockedNumber = partialMock.GenerateOrderNumber("ORD");
Console.WriteLine(mockedNumber); // 输出:MOCK-123456

几个需要注意的点

  • 这种部分Mock的方式,对于接口是完全通用的;如果是直接针对类进行Mock,那需要被替换/验证的方法必须是虚方法(virtual)或者抽象方法——因为NSubstitute是通过生成子类来实现Mock的,非虚方法没办法被重写。
  • 如果你的类没有实现接口,也可以直接对类本身创建部分Mock:
var realClass = new OrderService();
var classPartialMock = Substitute.For<OrderService>(realClass);
// 同样可以验证或替换虚方法
classPartialMock.GenerateOrderNumber(Arg.Any<string>()).Returns("CLASS-MOCK-789");

这样是不是比自己写Wrapper类省心太多啦?

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:24:00