Infinite jasmine timeout

2019-06-14 23:20发布

问题:

This is basically a follow-up to Remove timeout for single jasmine spec github issue.

The question:

Is it possible to make a single test never timeout?

The problem:

It is possible to set a timeout value globally via DEFAULT_TIMEOUT_INTERVAL or for every describe with beforeEach/afterEach or on a single it() block:

it('Has a custom timeout', function() {
  expect(true).toBeTruthy();
}, value in msec)

I'm interested in having a single spec never timeout. I've tried to follow the advice proposed in the mentioned github issue and use Infinity:

it('Has a custom timeout', function() {
  expect(true).toBeTruthy();
}, Infinity)

but, I've got the following error immediately after the tests got into the it() block:

Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL

I guess I cannot use Infinity as a timeout value, or I'm doing something wrong.


As a workaround, I can use a hardcoded large number instead, but I'd like to avoid that.

回答1:

Jasmine internally uses setTimeout to wait for specs to finish for a defined period of time.

According to this Q/A - Why does setTimeout() "break" for large millisecond delay values?:

setTimeout using a 32 bit int to store the delay

...

Timeout values too big to fit into a signed 32-bit integer may cause overflow in FF, Safari, and Chrome, resulting in the timeout being scheduled immediately. It makes more sense simply not to schedule these timeouts, since 24.8 days is beyond a reasonable expectation for the browser to stay open.

As soon as Infinity is greater than any other number the overflow occurs.

The max safe integer in this case is 231-1 = 2147483647. This value is finite, so the test won't actually run infinitely long, but as said I think 24.8 days is long enough.

You can define a constant to store this value:

jasmine.DEFAULT_TIMEOUT_INTERVAL = 2000;

var MAX_SAFE_TIMEOUT = Math.pow(2, 31) - 1;

describe('suite', function () {

  it('should work infinitely long', function (done) {

    setTimeout(function () {
      expect(true).toBe(true);
      done();
    }, 3000)

  }, MAX_SAFE_TIMEOUT);

});

See working sample here