单元测试中,无需依赖模拟时仍Mock被测对象依赖是否为最佳实践?
这其实是单元测试里挺多人纠结的问题,没法一刀切说“是”或“不是”,核心得看你的依赖(B和C)是什么类型,以及你写A的单元测试的目标是什么。
先明确单元测试的核心:只测A自己的逻辑,别把B/C的逻辑又重复测一遍。基于这个目标,咱们分两种场景拆解:
场景1:B/C是无副作用的纯逻辑类(比如工具类)
如果B和C是那种没有外部依赖、执行飞快、纯内存运算的类——比如B是字符串加密工具,C是日期格式化类,而且它们已经被充分测试过了——那完全没必要Mock,直接用真实实例创建A反而更好。
举个具体的例子:假设A是「订单金额计算器」,B负责算折扣,C负责算税费,三者都是纯数学逻辑。这时候用真实的B和C测试A,能更贴近生产环境的真实协作场景。如果哪天B的折扣规则改了(比如满100减20改成满100减30),A的测试会直接失败,帮你发现A是否需要跟着调整逻辑——要是你Mock了B/C,就会错过这种集成层面的问题,导致测试通过但生产出bug。
场景2:B/C有外部依赖或副作用
如果B和C涉及外部资源(比如数据库、第三方API)、有副作用(比如发邮件、写文件),或者执行很慢——哪怕它们已经测过了——Mock才是最佳实践。
比如B是「用户信息查询类」(需要连数据库),C是「邮件发送类」(调用第三方邮件服务)。这时候要是用真实的B和C测试A:
- 你的单元测试会变成集成测试,依赖外部资源,速度慢得离谱;
- 测试稳定性没法保证(比如数据库挂了、API限流);
- 还会产生真实副作用(比如给真实用户发测试邮件)。
这时候Mock B和C就很有必要:你可以让Mock的B返回固定的用户数据,让Mock的C只验证是否被调用过、参数是否正确,这样A的测试只专注于自己的核心逻辑(比如判断用户是否符合优惠条件,然后触发邮件发送),测试速度快、稳定性高,也不会搞出额外的麻烦。
回到你的具体问题
总结下来:
- 如果B/C是纯逻辑、无外部依赖的类:不用Mock,直接用真实实例,测试A和B/C的协作逻辑更靠谱;
- 如果B/C有外部依赖或副作用:必须Mock,保证A的单元测试是独立、高效、稳定的。
记住:Mock的本质是隔离非核心依赖,不是为了Mock而Mock。一切都要围绕“测试A的逻辑”这个核心目标来选择。
内容的提问来源于stack exchange,提问作者eyes enberg

