Jasmine — Timer, and Async Tests
Tags: webdev, programming, testing, javascript
Published: 2021-01-23 20:53:06

**Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62**

**Subscribe to my email list now at http://jauyeung.net/subscribe/**

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.