I am new to unit testing so I might be missing something, but how am I supposed to structure requirejs modules in order to make them fully testable? Consider the elegant revealing module pattern.
define([], function () {
"use strict";
var func1 = function(){
var data = func2();
};
var func2 = function(){
return db.call();
};
return {
func1 : func1
}
});
As far as I am aware of this is the most common pattern for building requirejs modules. Please correct me if I am wrong! So in this simplistic scenario I can easily test return values and behavior of func1 since it is global. However, in order to test func2 I also would have to return it's reference. Right?
return {
func1 : func1,
_test_func2 : func2
}
This makes the code slightly less pretty, but overall is still ok. However, if I wanted to mock func2 and replace its return value by using Jasmine spy I would not be able to since that method is inside a closure.
So my question is how to structure requirejs modules to be fully testable? Are there better patterns for this situation than revealing module pattern?
Are you sure you want to test the private function func2?
I think developers are missing the point of unit tests when they try writing tests for private functions.
Dependencies are what get us by the balls when developing software. And the more dependencies the tighter the squeeze . So if you have lots of tests dependant on the internal workings of a module it's going to be really painful when you want to change the internal implementation. So keep your tests dependant on the public interface, and keep the private stuff private.
My advice:
Design the public interface to your module.
Write a test against the public interface to specify some expected behaviour.
Implement the code needed to pass that test.
Refactor (if necessary)
Repeat from step 2, until all the functionality has been defined by tests, and all the tests pass.
During the implementation and refactoring stages the internals of the module will change. For example, func2 could be split up into different functions. And the danger is that if you have tests for func2 specifically, then you may have to rewrite tests when you refactor.
One of the main benefits of unit tests is that they ensure we do not break existing functionality when we change a module's internal workings. You start losing that benefit if refactoring means you need to update the tests.
If the code in func2 becomes so complex that you want to test it explicitly, then extract it into a separate module, where you define the behaviour with unit tests against the public interface. Aim for small, well tested modules that have an easy to understand public interface.
If you are looking for help with regards to unit testing I thoroughly recommend Kent Beck's book "TDD by example". Having poorly written unit tests will become a hindrance rather than a benefit, and in my opinion TDD is the only way to go.
If functions in a module call the module's other functions directly (i.e. by using references that are local to the module), there is no way to intercept these calls externally. However, if you change your module so that functions inside it call the module's functions in the same way code outside it does, then you can intercept these calls.
Here's an example that would allow what you want:
define([], function () {
"use strict";
var foo = function(){
return exports.bar();
};
var bar = function(){
return "original";
};
var exports = {
foo: foo,
bar: bar
};
return exports;
});
The key is that foo goes through exports to access bar rather than call it directly.
I've put up a runnable example here. The spec/main.spec.js file contains:
expect(moduleA.foo()).toEqual("original");
spyOn(moduleA, "bar").andReturn("patched");
expect(moduleA.foo()).toEqual("patched");
You'll notice that bar is the function patched but foo is affected by the patching.
Also, to avoid having the exports polluted by test code on a permanent basis, I've sometimes done an environmental check to determine whether the module is run in a test environment and would export functions necessary for testing only in testing mode. Here's an example of actual code I've written:
var options = module.config();
var test = options && options.test;
[...]
// For testing only
if (test) {
exports.__test = {
$modal: $modal,
reset: _reset,
is_terminating: _is_terminating
};
}
If the requirejs configuration configures my module (using config) so that it has a test option set to a true value then the exports will additionally contain a __test symbol that contains a few additional items I want to export when I'm testing the module. Otherwise, these symbols are not available.
Edit: if what bothers you about the first method above is having to prefix all calls to internal functions with exports, you could do something like this:
define(["module"], function (module) {
"use strict";
var debug = module.config().debug;
var exports = {};
/**
* #function
* #param {String} name Name of the function to export
* #param {Function} f Function to export.
* #returns {Function} A wrapper for <code>f</code>, or <code>f</code>.
*/
var _dynamic = (debug ?
function (name, f) {
exports[name] = f;
return function () {
// This call allows for future changes to arguments passed..
return exports[name].apply(this, arguments);
};
} :
_dynamic = function (name, f) { return f; });
var foo = function () {
return bar(1, 2, 3);
};
var bar = _dynamic("bar", function (a, b, c) {
return "original: called with " + a + " " + b + " " + c;
});
exports.foo = foo;
return exports;
});
When the RequireJS configuration configures the module above so that debug is true, it exports the functions wrapped by _dynamic and provides local symbols that allow referring to them without going through exports. If debug is false, then the function is not exported and is not wrapped. I've updated the example to show this method. It's moduleB in the example.
Related
Thus far I've worked only with relatively small projects (and mostly alone), but this time I have to collaborate with other programmers... basically because of that I must plan the structure of the website very carefully for the avoidance of spending hours debugging the code.
At this point I suppose doing that in the following manner. I divide my code in modules and store each module in a separate file inside an object (or a function) with a made-up name (lzheA, lzheB, lzheC etc.) to avoid conflicts whether an object with the same name was used in an another piece of code. When the document is loaded, I declare a variable (an object) that I use as a main namespace of the application. Properties of the object are the modules I defined before.
// file BI.lib.js
var lzheA = {
foo: function() {
},
bar: function() {
},
}
// file BI.init.js
function lzheK() {
BI.loadPage();
}
// file BI.loadPage.js
function lzheC() {
var result = document.getElementById('result');
result.innerHTML = "that worked";
}
// and so on
var lzheA,lzheB,lzheD,lzheE,lzheF,lzheG,lzheH,lzheI,lzheJ;
// doing the following when the document is loaded
var BI = {
lib: lzheA,
menu: lzheB,
loadPage: lzheC,
customScripts: lzheD,
_index: lzheE,
_briefs: lzheF,
_shop: lzheG,
_cases: lzheH,
_blog: lzheI,
_contacts: lzheJ,
init: lzheK,
}
BI.init();
https://jsfiddle.net/vwc2og57/2/
The question... is this way of structuring worth living or did I miss something because of lack of experience? Would the made-up names of the modules confuse you regardless of the fact that each one used only twice - while declaring the variable and assigning it to a property?
I consider the namespaces a good option when you want to modularize applications in Javascript. But I declare them in a different way
var myModule = myModule || {}; // This will allow to use the module in other places, declaring more than one specificComponent in other js file for example
myModule.specificComponent = (function(){
// Private things
var myVar = {};
var init = function() {
// Code
};
return {
init: init // Public Stuff
};
})();
If you want to call the init method, you would call it like this
myModule.specificComponent.init();
With this approach, i guarantee that the module will not be overwritten by another declaration in another place, and also I can declare internal components into my namespaces.
Also, the trick of just exposing what you want inside the return block, will make your component safer and you will be encapsulating your code in a pretty way.
Hope it helps
The module pattern is described by most people as:
var module = (function() {
// private fields
var a, b, c;
// private functions
function myFunction() {}
// public data (where you expose to outside)
return {
publicFunc: function() {}
};
})();
But the above code creates a single instance of the module. Does it really have to be a singleton?
Is the code below still a module pattern?
function module() {
// same code
return {
publicFunc: function() {}
};
}
Yes, a module pattern returns a singleton, but that's not really a practical limitation. You can use a module pattern to return a singleton factory function, and then invoke that factory function multiple times.
var point = (function() {
// Add private code here to make use of module pattern.
// If you don't have anything to keep private, then
// module pattern is overkill, as noted in the comments
return function(x,y) {
return {
x : x,
y: y
}
}
})();
var point1 = point(0,0);
var point2 = point(3,4);
Without using a factory function, you can also put your module pattern inside a loop and execute it multiple times (this isn't recommended as it is grossly inefficient):
var points = [];
for (var i=0; i<4; i++){
points[i] = (function module() {
// same code
return {
publicFunc: function() {}
};
})();
}
UPDATE: Added comment inside of first example per #North and #Bergi's feedback below
Yes, modules are singletons. A car has just one engine. Creating a second one simply doesn't make sense (unless you radically change the whole design, increase the load which any struts can take, etc).
The second pattern is the "class" pattern where you have many instances that behave similarly (think a bunch of cars).
I always thought of the module pattern as the non-singleton version. In fact, I do avoid singletons as much as possible, especially if they have state. They're a nightmare from a testing perspective, especially when written as a self calling function.
For me, the module pattern is all about encapsulating state. If I only use a single instance of the module, I just call it a singleton module.
Here is an article that catches the gist of it, at least how I see it.
I've been working on a simple project on Adobe Extend Script Toolkit and is having trouble implementing tests on private members. I have come up with a solution which is to expose the privates inside a callback to a special function. I'm not sure if this is a good pattern. I need suggestions.
Heres the pattern:
(function (global) {
var Loader, Require, Modules;
Require = 'Require Object';
Modules = 'Modules object';
Loader = {};
global.estk = global.estk || {};
global.estk.loader = Loader;
// This MUST be used for testing purposes only.
// Use this to test for private members.
global.estk.loader.__test__ = function (callback) {
callback.call(this, {
Require: Require,
Modules: Modules,
Loader: Loader
});
};
}($.global));
In my test file I can then call the exposed privates like this:
(function(global) {
#include '../estk/loader.jsxinc';
estk.loader.__test__(function (obj) {
$.writeln(obj.Require);
$.writeln(obj.Modules);
$.writeln(obj.Loader);
});
}($.global));
As a general rule: if you need to test private data members, you need to rethink how you're doing things. You should test that given a set of inputs, the output is what you expect. These inputs should enter at the same place they enter in the public-facing API.
Unit testing should test the public interface of your code. Testing private parts tends to result in brittle tests (tests that fail when the code changes but not the results).
See this answer as well.
So, to answer your question directly: I wouldn't say that your pattern is good. You shouldn't worry about testing private functions. Test behavior, not methods. Not every method needs a test.
This is my second weekend playing with Node, so this is a bit newbie.
I have a js file full of common utilities that provide stuff that JavaScript doesn't. Severely clipped, it looks like this:
module.exports = {
Round: function(num, dec) {
return Math.round(num * Math.pow(10,dec)) / Math.pow(10,dec);
}
};
Many other custom code modules - also included via require() statements - need to call the utility functions. They make calls like this:
module.exports = {
Init: function(pie) {
// does lots of other stuff, but now needs to round a number
// using the custom rounding fn provided in the common util code
console.log(util.Round(pie, 2)); // ReferenceError: util is not defined
}
};
The node.js file that is actually run is very simple (well, for this example). It just require()'s in the code and kicks off the custom code's Init() fn, like this:
var util = require("./utilities.js");
var customCode = require("./programCode.js");
customCode.Init(Math.PI);
Well, this doesn't work, I get a "ReferenceError: util is not defined" coming from the customCode. I know everything in each required file is "private" and this is why the error is occuring, but I also know that the variable holding the utility code object has GOT to be stored somewhere, perhaps hanging off of global?
I searched through global but didn't see any reference to utils in there. I was thinking of using something like global.utils.Round in the custom code.
So the question is, given that the utility code could be referred to as anything really (var u, util, or utility), how in heck can I organize this so that other code modules can see these utilities?
There are at least two ways to solve this:
If you need something from another module in a file, just require it. That's the easy one.
Provide something which actually builds the module for you. I will explain this in a second.
However, your current approach won't work as the node.js module system doesn't provide globals as you might expect them from other languages. Except for the things exported with module.exports you get nothing from the required module, and the required module doesn't know anything of the requiree's environment.
Just require it
To avoid the gap mentioned above, you need to require the other module beforehand:
// -- file: ./programCode.js
var util = require(...);
module.exports = {
Init: function(pie) {
console.log(util.Round(pie, 2));
}
};
requires are cached, so don't think too much about performance at this point.
Keep it flexible
In this case you don't directly export the contents of your module. Instead, you provide a constructor that will create the actual content. This enables you to give some additional arguments, for example another version of your utility library:
// -- file: ./programCode.js
module.exports = {
create: function(util){
return {
Init: function(pie) {
console.log(util.Round(pie, 2));
}
}
}
};
// --- other file
var util = require(...);
var myModule = require('./module').create(util);
As you can see this will create a new object when you call create. As such it will consume more memory as the first approach. Thus I recommend you to just require() things.
I am using QUnit, which is excellent.
I have enclosed my JS app in the (function () {})(); sandbox. This hides a lot of code that I don't want public, but I also need to test that code.
Here is an example of how this works:
(function () {
var PublicAPI = window.PublicAPI = {};
PublicAPI.publicFunction = function (foo) {
PrivateAPI.privateFunction(foo);
return 'bar';
};
var PrivateAPI = {};
PrivateAPI.privateFunction: function (foo) {
// Make secret stuff that never gets returned to the public
// Could be an AJAX call.
}
})();
So here I can easily unit test PublicAPI.publicFunction, but how will I test PrivateAPI.privateFunction ?
This similar question sums it up pretty well... The easiest is to not deal with the private methods, as they can change if they want... The public methods are the ones that need testing. If you want to test your internal functions you need to leave a hook of some sort for qunit to be able to find.
You can't. There is no way to access it from outside of that scope. Your only hope is to integration test it, i.e. test functions on the globally available object that are using your internal functions.
Better yet: don't make private functions. What's the big deal?