Mocha unit tests running with Karma - done() is not defined
Solution 1
In Mocha, the done
callback is for it
, before
, after
, beforeEach
, afterEach
. So:
describe('nothing', function() {
it('a silly test', function(done) {
var note = new Note;
note.should.not.eql(32);
done();
});
});
Here's the doc.
Solution 2
The test you are running in that example doesn't require the done() callback. It is not asynchronous. An example of when the done callback is need....
describe('Note', function() {
it('can be retrieved from database', function(done) {
var note = new Note();
cb = function(){
note.contents.should.eql("stuff retrieved from database");
done()
}
//cb is passed into the async function to be called when it's finished
note.retrieveFromDatabaseAsync(cb)
});
});
Your test should not have a done callback
describe('nothing', function() {
it('umm...', function() {
var note = new Note;
note.should.not.eql(32);
});
});
Only the 'it' function provides a done callback. describe does not. Your problem does not rest with karma. Your mocha tests are not defined correctly.
Solution 3
Holy %$#@!
I would never in a million years have thought this would barf:
describe('nothing', function(done) {
it('umm...', function() {
var note = new Note;
note.should.not.eql(32);
});
done(); // throws error that undefined is not a function
});
But this works just fine:
describe('nothing', function(done) {
it('umm...', function() {
var note = new Note;
note.should.not.eql(32);
});
setTimeout(function() {
done(); // MAGIC == EVIL.
}, 1000);
});
Jason Boyd
Updated on June 05, 2022Comments
-
Jason Boyd about 2 years
I'm trying to get tests written with Mocha to work running Karma, and they sort of work, but I cannot use the done() method to implement async tests, which essentially makes the tools useless to me. What am I missing?
karma.conf.js
module.exports = function(config) { config.set({ basePath: '../..', frameworks: ['mocha', 'requirejs', 'qunit'], client: { mocha: { ui: 'bdd' } }, files: [ {pattern: 'libs/**/*.js', included: false}, {pattern: 'src/**/*.js', included: false}, {pattern: 'tests/mocha/mocha.js', included: false}, {pattern: 'tests/should/should.js', included: false}, {pattern: 'tests/**/*Spec.js', included: false}, 'tests/karma/test-main.js' ], exclude: [ 'src/main.js' ], // test results reporter to use // possible values: 'dots', 'progress', 'junit', 'growl', 'coverage' reporters: ['progress', 'dots'], port: 9876, colors: true, // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG logLevel: config.LOG_WARN, autoWatch: true, // Start these browsers, currently available: // - Chrome // - ChromeCanary // - Firefox // - Opera (has to be installed with `npm install karma-opera-launcher`) // - Safari (only Mac; has to be installed with `npm install karma-safari-launcher`) // - PhantomJS // - IE (only Windows; has to be installed with `npm install karma-ie-launcher`) browsers: ['Chrome'], // If browser does not capture in given timeout [ms], kill it captureTimeout: 60000, // Continuous Integration mode // if true, it capture browsers, run tests and exit singleRun: false }); };
test-main.js (configuring RequireJS)
var allTestFiles = []; var pathToModule = function(path) { return path.replace(/^\/base\//, '../').replace(/\.js$/, ''); }; Object.keys(window.__karma__.files).forEach(function(file) { if (/Spec\.js$/.test(file)) { // Normalize paths to RequireJS module names. allTestFiles.push(pathToModule(file)); } }); require.config({ // Karma serves files under /base, which is the basePath from your config file baseUrl: '/base/src', paths: { 'should': '../tests/should/should', 'mocha': '../tests/mocha/mocha', 'pubsub': '../libs/pubsub/pubsub', 'jquery': '../libs/jquery/jquery-1.10.2', 'jquery-mobile': '//code.jquery.com/mobile/1.4.2/jquery.mobile-1.4.2.min' }, // dynamically load all test files deps: allTestFiles, // we have to kickoff jasmine, as it is asynchronous callback: window.__karma__.start });
tests/fooSpec.js
define(['music/note'], function(Note) { describe('nothing', function(done) { it('a silly test', function() { var note = new Note; note.should.not.eql(32); }); done(); }); ...
Though this is a contrived example, it succeeds if I remove the done() call. As it is, I get:
Uncaught TypeError: undefined is not a function at /Library/WebServer/Documents/vg/tests/mocha/fooSpec.js:8
This is the done() line. How/why is this not defined? I'm not understanding where else to configure Mocha (or with what options). Is there some sort of global namespace or meta-programming magic causing RequireJS to interfere with Mocha?
I'm running the tests in Chrome 33 on OS X 10.9.2, in case that is at all relevant. I've killed a ton of time on this and am ready to give up on automated testing :( -- had similar brick walls with QUnit/Karma/RequireJS and have not been able to find any alternative to successfully automate tests. I feel like an idiot.