一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

如何在大型工程中利用依赖注入重构模块以实现不改源码即可切换 Mock 数据

时间:2026-07-20 10:51:47 编辑:袖梨 来源:一聚教程网

无需修改业务逻辑代码即可替换真实服务为Mock数据,关键在于依赖倒置:通过接口抽象隔离实现、构造函数注入替代内部创建、提供可插拔Mock实现,并由构建配置或运行时参数控制具体实现注入。

不需要改业务逻辑代码,就能把真实服务换成 Mock 数据——关键在于把“依赖创建”从函数或类内部移出来,交给外部统一管理。只要接口一致,替换就只是换一个实例的事。

用接口抽象隔离实现细节

真实模块和 Mock 模块必须共用同一套方法签名和行为契约。比如定义一个获取用户信息的接口:

  • C++ 中用纯虚类:class IUserProvider { public: virtual User Get(int id) = 0; };
  • Go 中用 interface:type UserProvider interface { Get(id int) (User, error) }
  • TypeScript 中用 interface:interface UserProvider { get(id: number): Promise<User> }

业务代码只依赖这个接口,不关心背后是数据库查、HTTP 调用,还是内存 map 返回。

构造函数注入替代内部 new

把原来在类里直接 new 实例的地方,改成从外部传入。例如:

  • 重构前:class OrderService { private repo = new DatabaseRepo(); }
  • 重构后:class OrderService { constructor(private repo: UserProvider) {} }

这样测试时只需传入一个 Mock 实现,生产环境再传真实的 HTTP 或 DB 实例。C++ 可用智能指针 + 工厂函数;Go 直接传接口变量;TS 常配合 DI 容器如 InversifyJS 或手动传参。

构建可插拔的 Mock 实现

Mock 不是随便写个假函数,而是按接口完整实现,并支持预设响应、校验调用次数等:

  • 返回固定数据:MockUserProvider.Get(123) → User{ID: 123, Name: "test"}
  • 模拟失败路径:MockUserProvider.Get(999) → error("not found")
  • 记录调用痕迹:mock.Calls.Count("Get") == 2

这类 Mock 类通常不参与生产构建,仅在 test 目录下存在,编译时自动排除。

通过构建配置或运行时参数切换

最终如何决定用哪个实现?靠的是启动入口或构建脚本的控制逻辑:

  • CMake 中用 option(USE_MOCK "Enable mock providers" OFF) 控制源文件是否加入编译
  • Go 主程序中根据 -mock flag 创建不同 service 实例
  • TypeScript 项目用环境变量 NODE_ENV=test 加载对应 provider 注册表

源码完全不动,变的只是组装方式和注入源头。

热门栏目