主要观点:
- 介绍了在 Elixir 中使用模拟(mocks)的相关问题及解决方案,强调模拟应作为名词使用,避免滥用。
- 以外部 API 为例,说明直接模拟 HTTP 客户端的弊端,如耦合应用、影响测试并发等,提出用配置文件来配置不同环境下的 Twitter 客户端替代模拟。
- 强调明确的契约(contract)在测试中的重要性,通过定义行为(behaviour)来规范接口,避免模拟实体过度复杂导致的耦合。
- 指出测试大型系统的关键是找到合适的边界,每个使用模拟的测试都应有集成测试覆盖,以保证系统整体工作正常。
- 讨论了关于使代码“可测试”、将模拟作为局部变量、将模拟作为名词以及模拟库等常见问题。
关键信息:
- 2015 年 10 月 14 日 José Valim 发表关于 Elixir 中模拟的文章,近 2 年后发布 Mox 库。
- 模拟是模拟实体以受控方式模仿真实实体行为,应作为名词。
- 以 Twitter API 为例,直接模拟 HTTP 客户端会导致耦合和测试问题,应通过配置文件选择不同环境的 Twitter 客户端实现。
- 定义行为规范接口,如在 Elixir 中定义
MyApp.Twitter
行为,添加@behaviour
注解。 - 测试时需注意边界,每个使用模拟的测试应有集成测试,可利用
@tag
系统在 ExUnit 中配置测试运行。 - 对于使代码“可测试”的观点,应注重改进代码设计而非单纯为测试而改变生产代码,配置开销小。
- 可通过将依赖作为参数传递、定义协议等方式替代依赖配置文件。
- 模拟库应避免促进不良模式,遵循“模拟作为名词”规则。
重要细节:
- 示例代码中
MyApp.MyController
通过twitter_api
获取 Twitter 客户端并调用其方法,不同环境可配置不同的 Twitter 客户端实现。 - 强调明确契约可保护避免过度模拟、管理组件间复杂度、便于测试系统隔离复杂组件。
- 提及外部条件如速率限制可能使某些模拟解决方案不可行,可使用假的 HTTP 客户端或运行模拟服务器。
- 讨论了不同情况下处理依赖的方式,如作为参数传递、定义协议等,并给出相应示例代码。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。