Testing

webTiger Logo Wide

Asynchronous Testing with the Jasmine JS Test Framework

JasmineJS Logo

Jasmine provides a simple behaviour-driven development testing model that is simple to set up and execute. Where things become slightly clouded is when you need to deal with asynchronous events. For example, how do you test your modals work?

(If you aren’t familiar with Jasmine for unit testing, check out this article first.)

Fortunately, there are asynchronous features built into Jasmine too. Consider the Jasmine test file (JavaScript) below.

describe('My Tests', function () {

    var defaultTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;

    beforeEach(function () {
        // Before each test is run, set the timeout to 30 seconds.
        jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000; 
    });

    afterEach(function () {
       // After each test reset the timeout period.
       jasmine.DEFAULT_TIMEOUT_INTERVAL = defaultTimeout; 
    });

    describe('asynctest1_1', function () {

        beforeEach(function (done) {
            done();
        });

        afterEach(function (done) {
            done();
        });

        it('description of test here', function (done) {
            var finished = false;
            var timerId = setInterval(function () {
                // TODO: something asynchronous that sets the 'finished' flag when done.
                if (finished) {
                    clearInterval(timerId);
                    done();
                }
            , 250);
        });
    });
});Code language: JavaScript (javascript)

In order for the ‘done’ functions to be isolated, you need to encapsulate each test in it’s own ‘describe’ call. As long as you do that, you can perform your asynchronous tests as shown above.

What is happening is that by providing the ‘done’ function as a parameter Jasmine knows that the test is not complete when the function call returns, so it waits for the ‘done’ function to be called instead. If you are using ES6 or above then you can also provide a Promise instead of a function where we’ve used ‘done’ above.

Another way of performing asynchronous testing is to use the ‘await’ keyword, but this was only introduced in ECMAScript 2017 (ES6-2017) and so may not be supported by all browsers (its mainly MS Internet Explorer that won’t be using it). For example:

describe('More Tests', function () {
    beforeEach(async function() {
        // Run pre-test setup.
        // initialiseTestHarness returns a Promise, so execution will await 
        // its completion.
        await initialiseTestHarness(); 
    });

    it('asynctest2_1', async function() {
        // actionBeingTested returns a Promise, and execution will await 
        // its completion.
        const result = await actionBeingTested(); 

        // once the result has been returned, it can be evaluated as normal.
        expect(result).toEqual(expectedValue);    
    });
});Code language: JavaScript (javascript)