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

javascript - promise & mocha: done() in before or not? - Stack Overflow

programmeradmin3浏览0评论

I am reading some tutorials on promise tests in mocha. There is a piece of codes:

before(function(done) {
  return Promise.resolve(save(article)).then(function() {
    done();
  });
});

Why done() called in the then() in the before()? What is the difference between the above codes and the following codes:

before(function(done) {
  return Promise.resolve(save(article));
});

Thanks

UPDATE

My question is to pare with the following codes:

before(function() {
  return Promise.resolve(save(article));
});

Sorry for the typo.

I am reading some tutorials on promise tests in mocha. There is a piece of codes:

before(function(done) {
  return Promise.resolve(save(article)).then(function() {
    done();
  });
});

Why done() called in the then() in the before()? What is the difference between the above codes and the following codes:

before(function(done) {
  return Promise.resolve(save(article));
});

Thanks

UPDATE

My question is to pare with the following codes:

before(function() {
  return Promise.resolve(save(article));
});

Sorry for the typo.

Share Improve this question edited Aug 8, 2017 at 16:30 BAE asked Aug 8, 2017 at 16:03 BAEBAE 8,93623 gold badges98 silver badges182 bronze badges 0
Add a ment  | 

3 Answers 3

Reset to default 8

The first code snippet with the before hook returns a promise and calls done. In Mocha 3.x and over, it will result in this error:

Error: Resolution method is overspecified. Specify a callback *or* return a Promise; not both.

It used to be that it did not particularly matter if you used done and returned a promise, but eventually the Mocha devs figured that specifying both done and returning a promise just meant the test designer made a mistake and it was better to have Mocha pitch a fit rather than silently allow it.

In your 2nd snippet, you have the done argument and return a promise but Mocha will still wait for done to be called and will timeout. (It really should detect the argument and raise an error like in the 1st case, but it doesn't...)

Generally, if you are testing an asynchronous operation that produces a promise, it is simpler to return the promise than use done. Here's an example illustrating the problem:

const assert = require("assert");

// This will result in a test timeout rather than give a nice error
// message.
it("something not tested properly", (done) => {
    Promise.resolve(1).then((x) => {
        assert.equal(x, 2);
        done();
    });
});

// Same test as before, but fixed to give you a good error message
// about expecting a value of 2. But look at the code you have to
// write to get Mocha to give you a nice error message.
it("something tested properly", (done) => {
    Promise.resolve(1).then((x) => {
        assert.equal(x, 2);
        done();
    }).catch(done);
});

// If you just return the promise, you can avoid having to pepper your
// code with catch closes and calls to done.
it("something tested properly but much simpler", () => {
    return Promise.resolve(1).then((x) => {
        assert.equal(x, 2);
    });
});

With regards to the pletion of asynchronous operations, it works the same whether you are using it, before, beforeEach, after or afterEach so even though the example I gave is with it, the same applies to all the hooks.

I am not sure if I understood 100% the question, but the tests will not start until done is called.

 beforeEach(function(done) {
    setTimeout(function() {
      value = 0;
      done();
    }, 1);
  });

This test will not start until the done function is called in the call to beforeEach above. And this spec will not plete until its done is called.

  it("should support async execution of test preparation and expectations", function(done) {
    value++;
    expect(value).toBeGreaterThan(0);
    done();
  });

You don't have to pass done in your example, just:

before(function() {
  return Promise.resolve(save(article));
});

If you do pass done the test runner will expect to be called before continue, otherwise it will probably throw a timeout error.

In this particular case there is no functional difference. The callback, often called done, was introduced to handle asynchronous tests when using callbacks. Returning a Promise is sufficient, but note that you cannot define the done callback, because the test suite will wait until it's called. Use done when you can't easily return a Promise. In your case the second test will be infinite, because you define done, which you never actually call.

发布评论

评论列表(0)

  1. 暂无评论