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

关于经典TDD与Mockist测试的困惑求解

厘清单元测试中真实对象 vs Stub/Mock的困惑

这确实是单元测试领域里最容易让人纠结的问题之一,我来帮你拆解清楚核心差异和判断标准:

两种TDD流派的核心分歧

你提到的文章里已经点出了关键:单元测试其实有两种主流流派,它们对“隔离”的理解完全不同:

  • 经典TDD(芝加哥派):优先选择使用真实依赖,只有当真实依赖会带来问题时才用Stub/Mock。他们认为,只要依赖是纯逻辑、无外部副作用、快速且稳定的,直接用真实对象能让测试更贴近真实场景,也减少维护替身的成本。比如一个纯内存的数学计算类、字符串处理工具,完全可以直接在测试里实例化使用。
  • Mockist TDD(伦敦派):强调完全隔离被测类(SUT),所有外部依赖都必须用Stub/Mock替换。他们的目标是只验证SUT自身的逻辑是否正确,不关心依赖的工作状态,甚至假设依赖是完美的。

文档反例的本质原因

你看到的不推荐代码:

public int GetContosoPrice() { 
    var stockFeed = new StockFeed(); // NOT RECOMMENDED 
    return stockFeed.GetSharePrice("COOO"); 
}

这里的问题不是“用了真实对象”,而是这个真实对象(StockFeed)大概率带有外部依赖——比如它可能要调用第三方股票API、读取数据库或者访问文件系统。这类依赖会导致测试:

  • 运行速度慢(网络请求/DB操作耗时)
  • 不稳定(API可能宕机、返回数据随机变化)
  • 有副作用(比如触发API调用次数限制、产生测试垃圾数据)

如果StockFeed是一个纯内存的模拟类(比如硬编码返回固定价格),那肯定不会被标记为不推荐。

什么时候用真实对象?什么时候用替身?

给你一个简单的判断框架:

  • 用真实对象:当依赖满足以下所有条件时:
    1. 没有外部副作用(不碰网络、DB、文件、外部服务)
    2. 运行速度极快(纯内存计算)
    3. 行为稳定(输入固定则输出固定,不会随机变化)
  • 用Stub/Mock:当依赖存在以下任意一种情况时:
    1. 有外部副作用(需要和外部系统交互)
    2. 运行缓慢(会拖慢测试套件的执行速度)
    3. 行为不稳定(输出不可预测)
    4. 需要验证SUT和依赖的交互逻辑(比如是否调用了某个方法、调用了几次、传入了什么参数)

最后总结

两种流派没有绝对的对错,选择哪种取决于你的测试目标和项目场景:

  • 如果追求测试的真实性、减少维护成本,经典TDD更合适;
  • 如果需要严格隔离SUT逻辑、快速验证交互,Mockist TDD更高效。

关键是不要教条化——不要觉得“所有依赖都必须Stub/Mock”,也不要随便把带外部副作用的真实对象塞进测试里,根据依赖的特性和测试的目标灵活选择就好。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:54:02