Search code examples
javascriptasynchronousdojointernchai

assert(false) inside async xhr handler of async intern test doesn't fail the test


I've written an intern test that does some xhr calls (login, fetch data) that depend on each other. So, I've nested them, but still hope to be able to use the chai assertion library inside my handlers.

I find the test is not failed properly, it always hangs and finally intern reports:

FAIL: main - MySuite - Make some async requests.. (10012ms)
CancelError: Timeout reached on main - MySuite - Make some async requests..

This is depite having a line of code: assert(false, 'Oh no, something went wrong'); that is executed.

From what I've seen inside the assert library it throws exceptions which are expected to be caught higher up the call stack, but this approach isn't suitable for the call stack of an async request handler.

Can I use assert() style functions at this point in the code, or am I forced to reject the original dfd given me by this.async(timeout)?

This question is different to Async test doesn't error on fail in that he was misusing the original dfd from this.async() .. I am trying to not use that, and instead use the higher level abstrations of the chai assertion library.

My simplified test module:

/*jshint dojo:true */
/*global console:true */
'use strict';
define([
    'intern!tdd',
    'intern/chai!assert',
    'intern/dojo/request'
], function (test, assert, request) {

    console.log('Test has started to run.');
    var testTimeout = 10000;

    test.suite('MySuite', function () {
        test.test('Make some async requests..', function () {
            var dfd = this.async(testTimeout);

            var promise = request('http://dojotoolkit.org/js/dojo/1.8/release/dtk/dijit/themes/claro/claro.css')
            .then(function (res) {

                console.log('First request OK: ', res.length, ' chars.');
                // Make a second request
                request('http://dojotoolkit.org/css/print.css')
                .then(function (res2) {

                    console.log('Second  request OK: ', res2.length, ' chars.');

                    // Now pretend we hit an error
                    console.log('Faking an assert fail...');
                    assert(false, 'Oh no, something went wrong');

                    // We would have got here if it weren't for those pesky assertions
                    dfd.resolve('test passed');
                }, function (err) {
                    // Record the error
                    console.log('Inner Error handler was hit: ', err);
                    //Error Callback
                    //Ensure no HTTP errors raised.
                    dfd.reject.bind(dfd);
                });
            },

            function (err) {
                // Record the error
                console.log('Outer Error handler was hit: ', err);
                //Error Callback
                //Ensure no HTTP errors raised.
                dfd.reject.bind(dfd);
            });
        });
    });

});

intern.js:

// Learn more about configuring this file at <https://github.com/theintern/intern/wiki/Configuring-Intern>.
// These default settings work OK for most people. The options that *must* be changed below are the
// packages, suites, excludeInstrumentation, and (if you want functional tests) functionalSuites.
define([ 'intern/node_modules/dojo/has' ], function (has) {
    has.add('dojo-has-api', true);

    return {
        // Configuration options for the module loader; any AMD configuration options supported by the specified AMD loader
        // can be used here
        loader: {
            // Packages that should be registered with the loader in each testing environment
            packages: [
                'node',
                { name: 'testing', location: '.' }
            ]
        },

        // Non-functional test suite(s) to run in each browser
        suites: [ 'testing' /* 'myPackage/tests/foo', 'myPackage/tests/bar' */ ]

    }
});

shell output:

neek@alyssa:~/src/WIN/testing$ node node_modules/.bin/intern-client config=intern suites=internpromises
Defaulting to "console" reporter
Test has started to run.
First request OK:  135540  chars.
Second  request OK:  135540  chars.
Faking an assert fail...
FAIL: main - MySuite - Make some async requests.. (10009ms)
CancelError: Timeout reached on main - MySuite - Make some async requests..
    at Error (<anonymous>)

Solution

  • In asynchronous tests, you need to wrap the callback functions using dfd.rejectOnError(callback) if you just want the test to fail when an assertion fails, or dfd.callback(callback) if you want the test to fail if an assertion fails or succeed when no assertion fails. See the asynchronous testing portion of the documentation for more information.