Typescript / Node.js - 如何模拟传递依赖关系进行集成测试?

时间:2017-02-27 23:01:07

标签: node.js typescript supertest proxyquire

假设我有一条由控制器处理的Express路线。控制器使用服务,服务使用存储库与数据源通信。

我想使用Supertest创建一个集成测试来测试该路由:

test -> my Express app -> controller -> service -> repository -> data source

我的问题是我需要模拟存储库/数据源,才能运行测试!我想硬编码一些值,好像它们来自真实的数据源。我有什么选择?

在Java世界中,我将使用Spring或Guice的依赖注入,我会用这样的模拟版本替换存储库。在Typescript / Node.js世界中实现这种模拟的模式是什么?

我想使用普通的Javascript我可以使用Proxyquire及其Globally override require功能,从测试本身模拟存储库。但我不确定这是否适用于Typescript。

那么使用Typescript和Node.js从测试文件中模拟“深层”组件(传递依赖)的推荐方法是什么?

1 个答案:

答案 0 :(得分:7)

模块在第一次加载后被缓存,因此您可以先在测试文件中加载它们,然后使用像sinon这样的库来存储它们。

请考虑以下代码:

dcast(df_last, id ~ last_date, length, drop = FALSE, value.var = "last_date")

# Top Corner

   id 1979-12-29 1980-06-29 1980-12-28 1981-06-29 1981-12-28 1982-06-29 1982-12-28
 1:  1          0          0          0          0          0          0          0
 2:  2          0          0          0          0          0          0          0
 3:  3          0          0          0          0          0          0          0
 4:  4          0          0          0          0          1          0          0
 5:  5          0          1          0          0          0          0          0
 6:  6          0          0          0          0          0          0          0
 7:  7          0          0          0          0          0          0          0
 8:  8          0          0          0          0          0          0          0

您可以通过以下方式测试app.ts使用sinon对其依赖性进行测试:

// dependency.ts
export function foo(){
    return 'foo';
}

// app.ts
import {foo} from './dependency';
export default function main(){
    return  'winner ' + foo();
}

因此,基本上对于集成测试,您可以在启动应用程序之前导入和存根依赖项。我这样做了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,并将其与supertest一起使用。这将最终为您提供应用程序,但是在设置了存根依赖项之后!
  • 编写并运行测试,知道它将使用预定义数据