如何测试使用 async/await 的方法?

Posted

技术标签:

【中文标题】如何测试使用 async/await 的方法?【英文标题】:How to test a method that uses async/await? 【发布时间】:2018-06-29 00:40:53 【问题描述】:

我看过很多关于如何在单元测试中使用 async/await 的文章,但我的需求正好相反。

如何为使用 async/await 的方法编写测试?

我的规范无法在“等待”行之后访问任何代码。具体来说,规范在两个方面失败。

1) HelloWorld.otherCall 返回 undefined 而不是我指定的返回值

2) HelloWorld.processResp 永远不会被调用

class HelloWorld 

    async doSomething(reqObj) 
        try 
           const val = await this.otherCall(reqObj);
           console.warn(val); // undefined
           return this.processResp(val);
        
    



describe('HelloWorld test', function () 

    let sut = new HelloWorld(); //gross simplification for demo purposes

    describe('doSomething()', function () 
        beforeEach(function mockInputs() 
           this.resp = 'plz help - S.O.S.';
        );

        beforeEach(function createSpy() 
            spyOn(sut, 'otherCall').and.returnValue( $q.resolve(this.resp) );
            spyOn(sut, 'processResp');
        );

        it('should call otherCall() with proper arguments', function () 
            //this test passes   
        );

        it('should call processResp() with proper arguments', function () 
           sut.doSomething();
           $rootScope.$apply(); //you need this to execute a promise chain..

           expect(sut.processResp).toHaveBeenCalledWith(this.resp); 
           //Expected spy processResp to have been called with [ 'plz help SOS' ] but it was never called.
        );
    );
);

运行 angular 1.5 和 jasmine-core 2.6。

【问题讨论】:

【参考方案1】:

promise 的.then 被重载以处理promise 或值,await 是调用then 的语法糖。

所以没有理由要求你的间谍返回一个承诺,甚至是一个值。完全返回,即使undefined,应该触发await 触发,并启动你的async 函数的其余部分。

我相信您的问题是您没有等待doSomething 承诺解决,然后再尝试测试它的作用。这样的事情应该会让你更了解情况。

it('should call processResp() with proper arguments', async function () 
   await sut.doSomething();
   // ...
);

【讨论】:

【参考方案2】:

茉莉花有Asynchronous Support。您可能可以通过这种方式找到解决方案。

就个人而言,我认为您根本不应该测试这些方法。

测试状态表示我们正在验证被测代码是否返回正确的结果。

测试交互意味着我们正在验证被测代码是否正确调用了某些方法。

在大多数情况下,测试状态更好。

在你的例子中,

async doSomething(reqObj) 
    try 
       const val = await this.otherCall(reqObj);
       return this.processResp(val);
    

只要 otherCall 和 processResp 被单元测试很好地覆盖你就好了。

做某事应该包含在 e2e 测试中。

您可以在http://spectory.com/blog/Test%20Doubles%20For%20Dummies阅读更多相关信息

【讨论】:

以上是关于如何测试使用 async/await 的方法?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 react-hooks-testing-library 测试自定义 async/await 钩子

如何使用 async/await 处理同步方法/任务

使用Mocha / Chai和async / await验证是否抛出异常

关于async await的测试

小程序如何支持使用 async/await

如何在 Swift 5.5 中将 async/await 与 SwiftUI 一起使用?