Categories
Testing

Jasmine — Timer, and Async Tests

Spread the love

Testing is an important part of JavaScript.

In this article, we’ll look at how to create more complex tests with Jasmine.

Testing JavaScript Timeout Functions

We can use Jasmine to test JavaScript timeout functions.

We can use the jasmine.clock() method to do this.

For instance, we can write:

describe("Manually ticking the Jasmine Clock", function () {
  let timerCallback;

  beforeEach(function () {
    timerCallback = jasmine.createSpy("timerCallback");
    jasmine.clock().install();
  });

  afterEach(function () {
    jasmine.clock().uninstall();
  });

  it("causes a timeout to be called synchronously", function () {
    setTimeout(function () {
      timerCallback();
    }, 100);

    expect(timerCallback).not.toHaveBeenCalled();
    jasmine.clock().tick(101);
    expect(timerCallback).toHaveBeenCalled();
  });
});

to create a timerCallback spy which we can watch.

We call jasmine.clock().install() to create the Jasmine timer.

And we call jasmine.clock().uninstall() to remove it at the end.

Then we call tick to change the time to what we want.

This way, we can check is our setTimeout callback is called.

Also, we can use it to test setInterval .

For instance, we can write:

describe("Manually ticking the Jasmine Clock", function () {
  let timerCallback;

  beforeEach(function () {
    timerCallback = jasmine.createSpy("timerCallback");
    jasmine.clock().install();
  });

  afterEach(function () {
    jasmine.clock().uninstall();
  });

  it("causes a timeout to be called synchronously", function () {
    setInterval(function () {
      timerCallback();
    }, 100);

    expect(timerCallback).not.toHaveBeenCalled();

    jasmine.clock().tick(101);
    expect(timerCallback.calls.count()).toEqual(1);

    jasmine.clock().tick(102);
    expect(timerCallback.calls.count()).toEqual(2);
  });
});

Like with the setTimeout test, we change the clock to the time we want with the tick method.

The time is changed relative to the time that the last tick is called.

Mocking the Date

We can use the mockDate method to mock the date we want.

For instance, we can write:

describe("Manually ticking the Jasmine Clock", function () {
  let timerCallback;

  beforeEach(function () {
    timerCallback = jasmine.createSpy("timerCallback");
    jasmine.clock().install();
  });

  afterEach(function () {
    jasmine.clock().uninstall();
  });

  it("mocks time time", function () {
    const baseTime = new Date(2020, 0, 1);

    jasmine.clock().mockDate(baseTime);

    jasmine.clock().tick(50);
    expect(new Date().getTime()).toEqual(baseTime.getTime() + 50);
  });
});

We et the baseTime to a Date instance and then use that with mockDate to set the date to when we want.

Then we call tick to move the time.

And then we used getTime to get the current time after tick is called.

Async Support

Jasmine supports testing async code.

We can test async code with:

describe("Using callbacks", function () {
  beforeEach(function (done) {
    setTimeout(function () {
      value = 0;
      done();
    }, 1);
  });

  it("supports sequential execution of async code", function (done) {
    value++;
    expect(value).toBeGreaterThan(0);
    done();
  });
});

We have the beforeEach callback that has a setTimeout function call.

We call done in the callback so that the test code is run.

In the test code, the callback takes the done parameter to let us call done to indicate that the test is done.

To fail a test, we can use done.fail to fail the test.

For instance, we can write:

describe("Using callbacks", function () {
  var foo = function (x, callBack1, callBack2) {
    if (x) {
      setTimeout(callBack1, 0);
    } else {
      setTimeout(callBack2, 0);
    }
  };

  it("should not call the second callBack", function (done) {
    foo(true,
      done,
      function () {
        done.fail("Second callback has been called");
      }
    );
  });
});

We called done.fail in the 2nd callback so that if it’s run, the test will fail.

Conclusion

We can run a variety of tests that has timers and async code with Jasmine.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *