摩卡咖啡-如何测试未兑现的承诺?

时间:2018-09-11 19:49:23

标签: javascript testing promise mocha es6-promise

我正在测试一个返回诺言的函数。我想断言,在某些情况下,返回的承诺永远不会实现(既不解决也不拒绝)。

如何使用Mocha进行测试?


如果我运行以下命令:

describe('under certain conditions', function () {
  let promise;
  beforeEach(function () {
    promise = new Promise((resolve, reject) => {});
  });
  it('should hang forever', function () {
    return promise;
  });
});

我收到以下错误:

Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves

4 个答案:

答案 0 :(得分:3)

让我们先说一下,实际上,不可能验证承诺永不达成:在某个时候,您必须确定承诺完成花费了太长时间,然后假设在那之后它将永远不会解决。

以下是将这一点设置为5秒的解决方案:

it('should hang forever', function() {
  // Disable Mocha timeout for this test.
  this.timeout(0);

  // Wait for either a timeout, or the promise-under-test to settle. If the
  // promise that settles first is not the timeout, fail the test.
  return Promise.race([
    new Promise(resolve => setTimeout(resolve, 5000, 'timeout')),
    promise.then(
      () => { throw Error('unexpectedly resolved') },
      () => { throw Error('unexpectedly rejected') }
    )
  ]);
});

答案 1 :(得分:2)

robertklepanswer可以使用,但是您必须等待5秒钟才能完成测试。对于单元测试,5秒简直太长了。

如您所建议,您可以将lolex库集成到robertklep的解决方案中,以避免等待。

(我也使用Symbol代替字符串'timeout',以防您的诺言巧合地也解决为字符串'timeout'

import { install } from 'lolex';

describe('A promise', function () {
  let clock;
  before(function () { clock = install() });
  after(function () { clock.uninstall() });

  describe('under certain conditions', function () {
    const resolvedIndicator = Symbol('resolvedIndicator');
    const forever = 600000; // Defining 'forever' as 10 minutes
    let promise;
    beforeEach(function () {
      promise = Promise.race([
        new Promise(() => {}), // Hanging promise
        new Promise(resolve => setTimeout(resolve, forever, resolvedIndicator)),
      ]);
    });
    it('should hang forever', function () {
      clock.tick(forever);
      return promise.then((val) => {
        if (val !== resolvedIndicator) {
          throw Error('Promise should not have resolved');
        }
      }, () => {
        throw Error('Promise should not have rejected');
      });
    });
  });
});

答案 2 :(得分:1)

尝试一下:

describe('under certain conditions', function () {

    let promise;
    beforeEach(function () {
        promise = new Promise((resolve, reject) => {
        // promise.reject();
      });
    });

    it('should hang forever', function (done) {
        const onRejectOrResolve = () => {
            done(new Error('test was supposed to hang'));
        };
        promise
        .then(onRejectOrResolve)
        .catch(onRejectOrResolve);
        setTimeout(() => {
            done();
        }, 1000);
    });

  });

答案 3 :(得分:0)

您可以使用Promise.raceMDN)在永不解决的承诺和具有适当超时的参考承诺之间进行竞赛:

const p1 = new Promise((resolve, reject) => { });

const p2 = new Promise(function(resolve, reject) {
    setTimeout(resolve, 5 * 1000, 'promise2');
});


Promise.race([p1, p2])
.then(value => { 
  console.log(value); 
});