mercredi 4 février 2015

How to mock global variables (define, module, window) in mocha tests?

In the pursuit of 100% code coverage, I am attempting to use mocha to test that my javascript module is loading correctly under AMD , CommonJS/Node , and browser conditions. The pattern I'm using is below:


my-module.js



(function(global){

function MyClass(){}

// AMD
if(typeof define === 'function' && define.amd){
define(function(){
return MyClass;
});

// CommonJS/Node
} else if (typeof module !== 'undefined' && module.exports){
module.exports = MyClass;

// Browser
} else {
global.MyClass = MyClass;
}

})(this);


Since I am running my tests with node, define is never defined, and module is always defined; so the "CommonJS/Node" condition is the only one that ever gets tested.


What I have tried so far is something like this:


my-module.test.js



var MyClass = require('./my-module');

describe('MyClass', function(){
// suite of tests for the class itself
// uses 'var instance = new MyClass();' in each test
// all of these tests pass
});

describe('Exports', function(){
// suite of tests for the export portion
beforeEach(function(){
MyClass = null; // will reload module for each test
define = null; // set 'define' to null
module = null; // set 'module' to null
});

// tests for AMD
describe('AMD', function(){
it('should have loaded as AMD module', function(){
var define = function(){};
define.amd = true;

MyClass = require('./my-module'); // might be cached?
// hoping this reloads with 'define' in its parent scope
// but it does not. AMD condition is never reached.

expect(spy).to.have.been.called(); // chai spy, code omitted
});
});
});


I'm using spies to check if define has been called, but the module doesn't show any signs of ever being reloaded with define available to it. How can I achieve that?


And is there a safe way of nullifying module so that I can test the browser condition as well?


Aucun commentaire:

Enregistrer un commentaire