职责不清导致测试成本指数级上升:因违反隔离原则需mock过多依赖、用例爆炸、重构风险高;应通过测试意图倒逼设计,确保类只做一件事。

是的,C++测试写起来特别费劲,往往不是测试框架没配好,而是对象本身职责太杂、边界太模糊。
测试难写的典型信号:对象在“干所有人的活”
当你发现写一个单元测试要 mock 五六个依赖、构造一堆嵌套对象、还得手动管理生命周期时,问题大概率不在测试代码,而在被测对象的设计上。
-
ConfigManager不仅读配置,还解析 JSON、校验字段、触发重载回调、记录日志——它已经不是配置管理器,是“配置+日志+事件总线+校验引擎”的混合体 - 一个
NetworkService类里同时包含连接池管理、协议编解码、超时控制、重试策略、指标上报——每个职责都该有独立的类或模块 - 测试里频繁出现
std::shared_ptr<MockX>套std::unique_ptr<FakeY>再注入到TestableZ,说明接口契约没收敛,依赖关系网状缠绕
为什么职责不清会让测试成本指数级上升
职责混杂的对象天然违反单元测试的隔离原则。你无法只验证“读配置”这个行为,因为一调用 load() 就会顺带触发网络请求、写磁盘、发通知——这些都不是你要测的。
- mock 范围失控:本想只 stub 文件读取,结果发现
load()内部又调了validate(),而后者又依赖TimeProvider::now(),最后你得 mock 时间、文件、日志、配置源……四层深 - 测试用例爆炸:一个函数有 3 个外部依赖 + 2 个内部状态分支,组合下来至少需要 12 个测试用例才能覆盖主路径,这已经不是测试,是防御性编程
- 重构不敢动:改一行
parse()逻辑,得同步检查所有 mock 行为是否还匹配,因为没人能说清哪些测试用例真正依赖这个解析细节
怎么快速判断职责是否合理:用测试倒逼设计
别等写完再怀疑,直接拿测试意图反推——如果一个测试用例的名字里必须塞进三个以上动词,基本就出问题了。
立即学习“C++免费学习笔记(深入)”;
- 坏名字:
TestConfigManager_LoadAndValidateAndNotifyOnSuccess→ 它不该是一个类,该拆成ConfigLoader、ConfigValidator、ConfigNotifier - 坏 setup:
SetUp()里初始化了数据库连接、加载了全局配置、启动了 mock server —— 这说明被测对象和环境强耦合,而不是和接口耦合 - 坏断言:
EXPECT_CALL(mock_logger, log(_)).Times(AtLeast(1))出现在配置加载测试里 → 日志不是配置模块的职责,是横切关注点,该抽成装饰器或策略
真正难的不是写测试,是让对象只做一件事,并把这件事的输入、输出、失败条件定义清楚。一旦职责清晰,TEST 宏里的逻辑往往会自然变短,mock 变少,甚至有些类根本不需要 mock —— 因为它只依赖值类型或纯函数。


















