NodeJS:如何对依赖于其他异步调用的异步函数进行单元测试

时间:2018-05-16 08:48:26

标签: node.js unit-testing mongoose jestjs sinon

我有一个服务,我注入了一个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');
        }
    }
}

如果有人可以解释如何对这样一个复杂的(在我看来很复杂的)功能中进行单元测试,那将是最有帮助的。

1 个答案:

答案 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/