You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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是测试框架内置的异步测试通知机制,完整执行流程如下:

  1. 框架执行it函数时会先检测回调的入参数量:如果回调声明了1个入参(约定俗成命名为done,可自定义),就会自动判定这是异步测试,不会在同步代码跑完后直接结束用例。
  2. 框架会把一个内部的控制函数作为done参数传入你的测试回调:这个函数的唯一作用就是给框架发信号,告知「当前测试的所有逻辑已经执行完成,可以标记结果了」。
  3. 完整执行时序:
    • 框架调用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 06:15:00