JEST异步函数测试中done回调的运行原理相关问题咨询
异步测试
done参数运行原理解答 为什么Code1会提前退出
JS是单线程基于事件循环执行的,request发起的网络请求属于异步IO操作:你调用request的时候只是把请求发出去,把收到响应后要执行的回调函数暂存到事件队列,不会阻塞后续代码执行。
而Mocha/Jest这类主流JS测试框架默认把无参数的it回调判定为同步测试:只要it回调的同步代码执行完,就会立刻标记这个测试用例结束,根本不会等异步回调里的断言执行,所以Code1里的断言要么不会被触发,要么报错也不会被框架捕获。
Code-1 问题代码
describe("testing server functionalities", () => { // test case it("server handles a function", () => { request('some link', (error, response, body) => { var expected = "1410"; expect(expected).to.be.equal(body); }) }) });
Code2的运行逻辑
你用到的done是测试框架内置的异步测试通知机制,完整执行流程如下:
- 框架执行
it函数时会先检测回调的入参数量:如果回调声明了1个入参(约定俗成命名为done,可自定义),就会自动判定这是异步测试,不会在同步代码跑完后直接结束用例。 - 框架会把一个内部的控制函数作为
done参数传入你的测试回调:这个函数的唯一作用就是给框架发信号,告知「当前测试的所有逻辑已经执行完成,可以标记结果了」。 - 完整执行时序:
- 框架调用
it的回调函数,传入内置的done控制函数 - 执行
request发起网络请求,将响应回调注册到事件队列,it回调的同步代码执行完毕 - 框架进入等待状态,同时启动超时计时(默认一般为2000ms,超时会直接抛出测试失败错误)
- 网络请求响应返回,事件循环调度执行
request的回调函数:先执行断言校验逻辑,之后调用done() - 框架接收到
done()的调用,立刻终止等待计时,标记当前测试用例的执行结果,进入下一个测试流程
- 框架调用
Code-2 修复后代码
describe("testing server functionalities", () => { // test case it("server handles a function", (done) => { request('some link', (error, response, body) => { var expected = "1410"; expect(expected).to.be.equal(body); done(); }) }) });
补充说明
如果异步执行过程中出现错误,你可以把错误对象作为参数传入done(),框架会直接标记该测试用例失败,并打印对应的错误信息,示例:
it("server handles a function", (done) => { request('some link', (error, response, body) => { if (error) return done(error) // 直接抛出请求错误 var expected = "1410"; expect(expected).to.be.equal(body); done(); }) })
内容的提问来源于stack exchange,提问作者Sai
相关产品推荐
相关产品推荐

