Mock RequireJS define dependencies with config.map
- by Aligned
Originally posted on: http://geekswithblogs.net/Aligned/archive/2014/08/18/mock-requirejs-define-dependencies-with-config.map.aspxI had a module dependency, that I’m pulling down with RequireJS that I needed to use and write tests against. In this case, I don’t care about the actual implementation of the module (it’s simple enough that I’m just avoiding some AJAX calls). EDIT: make sure you look at the bottom example after the edit before using the config.map approach. I found that there is an easier way. I did not want to change the constructor of the consumer as I had a chain of changes that would have to be made and that would have been to invasive for this task. I found a question on StackOverflow with a short, but helpful answer from “Artem Oboturov”. We can use the config.map from RequireJs to achieve this. Here is some code: A module example (“usefulModule” in Common/Modules/usefulModule.js): define([], function() {
"use strict";
var testMethod = function() { ... };
// add more functionality of the module
return { testMethod; }
});
A consumer of usefulModule example:
define([
"Commmon/Modules/usefulModule"
],
function(usefulModule) {
"use strict";
var consumerModule = function(){
var self = this;
// add functionality of the module
}
});
Using config.map in the html of the test runner page (and in your Karma config –> I’m still trying to figure this out):
map: {'*':
{
// replace usefulModule with a mock
'Common/Modules/usefulModule': '/Tests/Specs/Common/usefulModuleMock.js'
}
}
With the new mapping, Require will load usefulModuleMock.js from Tests/Specs/Common instead of the real implementation.
Some of the answers on StackOverflow mentioned Squire.js, which looked interesting, but I wasn’t ready to introduce a new library at this time.
That’s all you need to be able to mock a depency in RequireJS. However, there are many good cases when you should pass it in through the constructor instead of this approach.
EDIT: After all that, here’s another, probably better way:
The consumer class, updated:
define([
"Commmon/Modules/usefulModule"
],
function(UsefulModule) {
"use strict";
var consumerModule = function(){
var self = this;
self.usefulModule = new UsefulModule();
// add functionality of the module
}
});
Jasmine test:
define([
"consumerModule",
"/UnitTests/Specs/Common/Mocks/usefulModuleMock.js"
], function(consumerModule, UsefulModuleMock){
describe("when mocking out the module", function(){
it("should probably just override the property", function(){
var consumer = new consumerModule();
consumer.usefulModule = new UsefulModuleMock();
});
});
});
Thanks for letting me think out loud :-).