Typescript / Node.js - 如何模拟集成测试的传递依赖项?
Posted
技术标签:
【中文标题】Typescript / Node.js - 如何模拟集成测试的传递依赖项?【英文标题】:Typescript / Node.js - How to mock transitive dependencies for integration testing? 【发布时间】:2017-07-18 18:03:05 【问题描述】:假设我有一个由控制器处理的 Express 路由。控制器使用服务,服务使用存储库与数据源通信。
我想使用Supertest 创建一个集成测试来测试该路由:
test -> my Express app -> controller -> service -> repository -> data source
我的问题是我需要 mock 存储库/数据源来运行测试!我想硬编码一些值,就好像它们来自真实数据源一样。我有哪些选择?
在 Java 世界中,我会在 Spring 或 Guice 中使用依赖注入,并且我会以这种方式将存储库替换为模拟版本。在 Typescript/Node.js 世界中实现这种模拟的模式是什么?
我想如果使用纯 javascript,我可以使用 Proxyquire
及其 Globally override require 功能,从测试本身模拟存储库。但我不确定这是否适用于 Typescript。
那么,使用 Typescript 和 Node.js 从测试文件中模拟“深层”组件(传递依赖)的推荐方法是什么?
【问题讨论】:
如果你使用的是普通的 Node 而不是 Typescript,护照的创建者有一个漂亮的库,叫做electrolyte,它可以进行依赖注入/IoC。您设置了文件夹,它将使用其IoC.use(..)
函数以相反的顺序查找,因此在我的测试引导文件中,我添加了我的 mocks 文件夹,以便它首先在那里查找,并将解析我的模拟数据源而不是我的其他文件夹或节点模块。
我为 Typescript 创建了一个测试库,可以很容易地模拟依赖项,无论它们在依赖项链中的哪个位置:ts-mock-imports
【参考方案1】:
模块在第一次加载后会被缓存,因此您可以先将它们加载到测试文件中,然后使用 sinon 之类的库对它们进行存根。
考虑以下代码:
// dependency.ts
export function foo()
return 'foo';
// app.ts
import foo from './dependency';
export default function main()
return 'winner ' + foo();
您可以通过以下方式测试 app.ts 与 sinon 的依赖关系:
import * as Dependency from '../src/dependency';
import main from '../src/app';
describe('test dependency', () =>
var fooStub;
beforeEach(() =>
fooStub = sinon.stub(Dependency, 'foo');
fooStub.returns('la la lang');
);
afterEach(()=>
fooStub.restore();
)
it('uses stubbed dependency', ()=>
expect(main()).to.be.equal('winner la la lang');
);
it('can return different values on other tests', ()=>
fooStub.returns('moonlight');
expect(main()).to.be.equal('winner moonlight');
);
);
所以基本上对于您的集成测试,您可以在启动应用程序之前导入和存根您的依赖项。我已经创建了一个app.proxy.ts
文件:
app.proxy
中导入您的存储库并将其存根以返回预定义的数据。设置好存根后,导入真实的app.ts
并导出。
在您的集成测试文件中,导入 app.proxy
而不是 app 并将其与 supertest 一起使用。这将最终为您提供应用程序,但在设置存根依赖项之后!
编写并运行测试,知道它将使用预定义的数据
【讨论】:
以上是关于Typescript / Node.js - 如何模拟集成测试的传递依赖项?的主要内容,如果未能解决你的问题,请参考以下文章
Node.js 和 Typescript,如何动态访问导入的模块
如何清理 Node.js 和 Typescript 中的响应正文
Typescript / Node.js - 如何模拟集成测试的传递依赖项?
如何删除多行 typeorm - postgresql 和 node.js(typescript)