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.