代码之家  ›  专栏  ›  技术社区  ›  VRN.dev

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

  •  2
  • VRN.dev  · 技术社区  · 7 年前

    我有一个服务,我将mongoose模型注入其中,然后我的express routes使用该服务来执行某些功能。如何对下面的代码进行单元测试一直困扰着我,因为有多个异步调用来检索DB数据以进行一些计算,然后返回结果。

    我是异步单元测试新手,正在将Jest 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 回复  |  直到 7 年前
        1
  •  2
  •   Simon Bruneaud    7 年前

    语法问题

    如果只是语法问题,可以按如下方式使用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 因为它是一个异步函数(返回一个承诺)。


    外部依赖项规范

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

    将外部依赖项传递给服务类的构造函数。

    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/