我有一个服务,我注入了一个mongoose模型,然后我的快速路由使用此服务来执行某些功能。我对如何对下面的代码进行单元测试感到困惑,因为有多个异步调用来检索DB数据以进行一些计算,然后返回结果。
我是异步单元测试的新手,我正在使用jon runner和sinon。
// Service.ts
export default class Service {
constructor(private dbModel){}
public async problemFunc(arg1, arg2, arg3) {
// validate args
let data1;
let data2;
let data3;
try {
data1 = await SomeOtherService1.getData();
}
catch(e) {
return e;
}
try {
data2 = await SomeOtherService2.getData();
}
catch(e) {
return e;
}
try {
data3 = await this.dbModel
.findById(arg1)
.where('some_field')
.exists(false);
}
catch(e) {
return e;
}
const calcResult = CalculationService.calc(arg1, data1, data2, data3);
if (calcResult) {
await this.dbModel.findByIdAndUpdate(arg1, calcResult);
return this.dbModel.findById(arg1);
} else {
return new Error('Fail');
}
}
}
如果有人可以解释如何对这样一个复杂的(在我看来很复杂的)功能中进行单元测试,那将是最有帮助的。
答案 0 :(得分:1)
如果它只是一个语法问题,您可以使用如下的mocha:
describe('my test suite', () => {
it('should return valid data', async () => {
let service = new Service();
let res = await service.problemFunc({...});
expect(res).to.equal(...);
});
});
如果您希望problemFunc
抛出错误,则应使用npm模块chaiAsPromised
,因为它是异步函数(返回承诺)。
在这里,您将多个外部依赖关系与业务逻辑混合在一起。为了测试这种外部依赖关系,你应该使用依赖注入。
您可以通过Service类的构造函数传递外部依赖项。
constructor(private externalService1, private externalService2){
this.externalService1 = externalService1;
this.externalService2 = externalService2;
}
然后你的方法应该是这样的:
async problemFunc() {
let data1 = await this.externalService1.getData();
let data2 = await this.externalService2.getData();
}
因此,您可以模拟测试套件中的外部依赖项:
describe('my test suite', () => {
it('should return valid data', async () => {
let fakeDb1 = {
getData: () => { return {}; }
}
let fakeDb2 = {
getData: () => { return {}; }
}
let service = new Service(fakeDb1, fakeDb2);
let res = await service.problemFunc({...});
expect(res).to.equal(...);
});
});
这篇精心撰写的文章清单可能会有所帮助: https://enterprisecraftsmanship.com/2015/06/29/test-induced-design-damage-or-why-tdd-is-so-painful/