Is done required in async Jest tests?

半世苍凉 提交于 2021-02-20 09:42:07

问题


I'm having an argument with a co-worker about done() in Jest tests.

He's orders of magnitude more experienced with JavaScript than I am, and I came in after async/await was generally accepted, plus came from a .NET environment, so I was used to it.

I write my tests like this:

it("should return 200 OK for POST method", async () => {
    await request(app).post("SOMEENDPOINT")
      .attach("file", "file")
      .expect(200);
});

He's more used to promises so will write his tests like this:

it("should return 200 OK for POST method", (done) => {
  request(app).post("SOMEENDPOINT")
    .attach("file", "file")
    .expect(200, done);
});

He's fine with my push to async/await, but insists I have to include done, such that I'm either doing his version modified version:

it("should return 200 OK for POST method", async (done) => {
  await request(app).post("SOMEENDPOINT")
    .attach("file", "file")
    .expect(200, done);
});

Or:

it("should return 200 OK for POST method", async (done) => {
    const res = await request(app).post("SOMEENDPOINT")
     .attach("file", "file");
    
    expect(res.status).toBe(200);
    done();
});

While I recognize calling done() is entirely necessary when it's included as a parameter, I was under the impression it is wholly unnecessary when using async/await in this context.

Request is supertest.request.

My question is, do I need to use done at all with async/await?


回答1:


There's never a need for done and async on the same test function. Pick one or the other, or, in this case, return the promise directly:

it("should return 200 OK for POST method", () =>
  request(app).post("SOMEENDPOINT")
    .attach("file", "file")
    .expect(200)
);

Jest will await any returned promise which means we can always manually construct and return a promise without async or done. This is redundant since we already have a promise at hand, but the following pattern is possible, if only for illustrative purposes:

it("should return 200 OK for POST method", () => {
  return new Promise((resolve, reject) => {
    request(app).post("SOMEENDPOINT")
      .attach("file", "file")
      .expect(200, resolve)
      .catch(err => reject(err))
    ;
  });
});

done is typically used for testing asynchronous callbacks (think basic Node library utilities in the fs module). In these cases, it's more elegant to add the done parameter and invoke it in the callback than it is to promisify the callback by hand. Essentially, done is a shortcut to promisification that abstracts out the new Promise boilerplate shown above.

Note that done can accept a parameter which is treated as an error (see the docs). This should go into any catch blocks to avoid a timeout and confusing error when the main line code throws before calling done:

it("should return 200 OK for POST method", done => {
  request(app).post("SOMEENDPOINT")
    .attach("file", "file")
    .expect(200, done)
    .catch(err => done(err))
  ;
});


来源:https://stackoverflow.com/questions/58713379/is-done-required-in-async-jest-tests

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!