首页 文章

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

提问于
浏览
0

我有一个服务,我注入了一个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 回答

  • 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 ,因为它是异步函数(返回一个promise) .


    外部依赖项规范

    在这里,您将多个外部依赖项与业务逻辑混合在一起 . 为了测试这种外部依赖关系,您应该使用依赖注入 .

    您通过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/

相关问题