最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Is done required in async Jest tests? - Stack Overflow

programmeradmin10浏览0评论

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?

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?

Share Improve this question edited Jan 15, 2021 at 23:48 ggorlen 57k8 gold badges110 silver badges150 bronze badges asked Nov 5, 2019 at 14:23 Jason St. JacquesJason St. Jacques 4031 gold badge4 silver badges14 bronze badges 2
  • 5 As you can see in the documentation, it's not needed: jestjs.io/docs/en/tutorial-async.html#async-await – Felix Kling Commented Nov 5, 2019 at 14:27
  • That was my original argument as well. – Jason St. Jacques Commented Nov 5, 2019 at 14:42
Add a comment  | 

1 Answer 1

Reset to default 10

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))
  ;
});
发布评论

评论列表(0)

  1. 暂无评论