4
votes

This seems to be a kind of Search for the Holy Grail, but I'm looking for a setup for a JavaScript unit testing environment. The requirements are:

  • testing Requirejs AMD modules
  • isolate each module by mocking out dependencies
  • testable in the browser during development
  • testable in a headless environment for continuous integration

Everything except the headless mocking seems to be straight forward.

So far, I've tested JS-Test-Driver, Karma, and Phantomjs, and for mocking, I've used Squire and Isolate -- as well as an implementation of the code in the answer here and nothing seems to work exactly right. The main problem I keep running into again and again is that the test framework returns before all the tests have run -- primarily because the mocks need their own require() dependencies.

Any help (or scaffold) would really help!

[edit]

I've put up a basic, working Karma project on Github with some sample mocked tests, using chai-expect as the matching library. I'll try to add more useful documentation, but if you're familiar with Karma, it should be pretty simple to extend. Just git clone and then npm install to get it running.

1

1 Answers

5
votes

Usually every test framework allows you to do asynchronous tests and starting tests manually which should be what you need.

QUnit

For QUnit you need to set the autostart setting to false to enable kicking tests off manually:

QUnit.config.autostart = false;

require(['test/qunit/test.js'], function() {
    QUnit.start();
});

If you load things asynchronously during tests, just use QUnits stop() and start() methods:

test('something that loads asynchronously', function() {
    stop();
    define(['something'], function(sth) {
        ok(sth, 'Something loaded');
        start();
    });
});

Mocha

Mocha works very similar:

/*globals mocha */
mocha.setup('bdd');

require([ 'test/mocha/test.js' ], function() {
    mocha.run();
});

And asynchronous tests are even nicer by declaring a parameter which will be the callback for your spec:

describe('an async something', function() {
    it('loads the dependency', function(done) {
        define(['something'], function(sth) {
            ok(sth, 'Something loaded');
            done();
        });
    });
});

This should usually work. One thing to keep in mind that tests might not always run in the same order if you load your test files with RequireJS.