I have a requirejs module created with the following pattern:
// foo.js
define(function(){
var x = 0;
function doStuff(){
return ++x;
}
return { doStuff: doStuff };
});
And a QUnit test which looks something like this:
// testfoo.js
define(['QUnit, foo'], function(QUnit, foo){
function setup(){
//...?
}
function teardown(){
//...?
}
function runTests(){
QUnit.test('foo counter remains at 1 on multiple tests', function(assert){
assert.equal(foo.doStuff(), 1); // this will work
});
QUnit.test('foo counter remains at 1 on multiple tests', function(assert){
assert.equal(foo.doStuff(), 1); // this obviously won't
});
}
return runTests;
});
How can I reset foo for each test?
I would like to keep foo a revealing module, i.e. not converting it to a constructor function with an altered prototype.
I tried var foo = require('foo');, but since requirejs is AMD based, it will complain about things getting loaded in the wrong order.
I suggest checking out SquireJS to create an isolated context for your tests. Squire is designed to inject mock dependencies by creating an isolated RequireJS context. A side effect of this is that the 'foo' library will be reload each time you call injector.require(), resetting the state of your library. The only downside is that your tests will need to be asynchronous.
// testfoo.js
define(['Squire', 'foo'], function (Squire, foo) {
'use strict';
QUnit.start();
QUnit.module('foo', {
setup: function () {
},
teardown: function () {
}
});
QUnit.test('Testing foo counter in main context.', 2, function (assert) {
assert.equal(foo.doStuff(), 1); // this will work
assert.equal(foo.doStuff(), 2); // this should work also.
});
QUnit.test('Testing foo counter in context created by Squire.', 1, function (assert) {
var done = assert.async(),
injector = new Squire();
injector.require([
'foo'
], function (foo) {
assert.equal(foo.doStuff(), 1); // this will work.
done();
});
});
});
I've posted a sample project here: qunit-squirejs
While this certainly isn't the cleanest way about it, by saving the function as a string, and recreating the function before each test, you can accomplish the same effect.
var fooString = foo.toString();
QUnit.testStart(function() { eval('foo = ' + fooString});
Related
I have an if-else statement in a function. I want to test both cases. When the instance is initiated, self.count is set to 1. When I run my test, it goes to the false statement. How can I make self.count = 2 to go into the else statement?
Test:
it('verify change', function () {
spyOn(this.instance, 'change').and.callThrough();
this.instance.change('messageBoard');
expect(this.instance.change).toHaveBeenCalled();
});
Javascript:
self.count = 1;
self.change = function change() {
if(self.count <= 1) {
// do stuff
} else {
// do stuff
}
};
I know I can use this.object.method.and.returnValue() to make a method return a value, but I don't know how to do it with variables.
So it seems i do not need to mock the variables. I can just assign it within the test like:
it('verify change', function () {
this.instance.count = 2; // this would nake it go to the else block
spyOn(this.instance, 'change').and.callThrough();
this.instance.change('messageBoard');
expect(this.instance.change).toHaveBeenCalled();
});
Given a data structure that satisfies some invariants, I would like to test the state of an instance of the data structure after various operations. What is the best way to do this?
describe('data-structure', function() {
var x;
beforeEach(function() {
x = getDataStructure();
});
describe('satisfies invariants', function() {
// run tests on 'fresh' x
it('should ...', function() {
// ...
});
// ...
});
describe('operation 1', function() {
it('should preserve invariants', function() {
x.doSomething();
// run 'satisfies invariants' tests on modified x
});
});
});
I thought about using an afterEach hook, but I do not think x is preserved there?
afterEach(function() {
// somehow run 'satisfies invariants' test
});
It maybe be that I can refactor 'satisfies invariants' into a method, but it would be nice if mocha could report which invariant-tests failed for each operation, e.g.
data-structure
satisfies invariants
should satisfy invariant 1 ...
...
operation 1
should satisfy invariant 1 ...
...
operation 2
should satisfy invariant 1 ...
...
Edit
Using the structure
describe('data-structure', function() {
var x;
describe('satisfies invariants', function() {
afterEach(function() {
it('should satisfy invariant 1', function() {
// x.value === a again
// ...
});
// ...
});
it('should work after operation 1', function() {
x = getDataStructure(); // x.value === a
x.operation1(); // x.value === b
});
it('should work after operation 2', function() {
x = getDataStructure();
x.operation2();
});
// ...
});
});
does not seem to preserve the changes to x.
It follows an example, let me know if I forget something of what we have discussed:
var assert = require('assert');
describe('data-structure', function() {
var x;
beforeEach(function() {
// freshly created data structure for each describe block below
x = getDataStructure;
});
describe('satisfies invariants', function() {
after(function() {
// it executes those tests only once after all the it block below
assert(x); // put your tests here
});
it('op 1.1', function() {
do_something_on(x);
});
it('op 1.2', function() {
// keep in mind that x is the same instance of the previous test
do_something_else_on(x);
});
// so on
});
describe('satisfies something else', function() {
// here you have a new instance of x, because of the outer beforeeach
after(function() {
// it executes those tests only once after all the it block within this describe block
assert(x); // put your tests here
});
it('op 2.1', function() {
do_something_on(x);
});
it('op 2.2', function() {
// keep in mind that x is the same instance of the previous test, but not the one used in 1.2
do_something_else_on(x);
});
// so on
});
// so on
});
This piece of code should give you an idea of which instance is accessible and where.
If it lacks something, let me know and I'll have a go to fix it.
The Problem
Mocha does not support putting it inside a hook like you do in your last snippet. (afterEach is a hook). In some trivial cases you may get the desired behavior but that's just luck. Once you move on to more complicated test suites, you won't get the behavior your expect.
Moreover, I suggest that afterEach is the wrong place for that kind of test. You should use the hooks only to setup and tear down your test environment and not for performing assertions on the state of your code. Mocha treats any failure in a hook as "the test suite is broken, abort!!" rather than as a test failure. Look at this example, for instance:
var assert = require('assert');
describe("test", function () {
var x;
beforeEach(function () {
x = { foo: 'something' };
});
afterEach(function () {
assert(x.foo === 'something');
});
it("one", function () {});
it("two", function () {
x.foo = 'something else';
});
it("three", function () {});
});
In theory there's no reason test three should not run but when the failure occurs in the afterEach hook after test two is run, Mocha will just stop running tests there. The output (omitting the final stack trace) is:
test
✓ one
✓ two
1) "after each" hook
2 passing (14ms)
1 failing
Note how two is marked as passing but the hook failed. And note how three is never even attempted. As soon as there is a failure in a hook, Mocha stops right there.
The Solution
You should just create a function that you call from each test to test your invariants. For instance:
var assert = require('assert');
describe("test", function () {
var x;
beforeEach(function () {
x = { foo: 'something' };
});
function testInvariant() {
assert(x.foo === 'something');
}
it("one", function () {
testInvariant();
});
it("two", function () {
x.foo = 'something else';
testInvariant();
});
it("three", function () {
testInvariant();
});
});
If you run Mocha on the code above, you'll get (again, omitting the final stack trace):
test
✓ one
1) two
✓ three
2 passing (10ms)
1 failing
two was marked as failed and Mocha moved on to run three, which was successful.
If you don't want to write testInvariant() in each test you could create a function that adds it for you. For instance:
var assert = require('assert');
describe("test", function () {
var x;
beforeEach(function () {
x = { foo: 'something' };
});
function makeTest(name, fn) {
it(name, function () {
fn();
assert(x.foo === 'something');
});
}
makeTest("one", function () {
});
makeTest("two", function () {
x.foo = 'something else';
});
makeTest("three", function () {
});
});
This produces the same output as the previous code snippet.
Overview
I've been using the Revealing Module Pattern for a few months and I'm looking for an alternative or variation on this pattern that will solve both issues I'm currently having with event handlers and testability. I know I could come up with some combination of what I have below to solve my problem, but I'm hoping to find a clean alternative that I could use consistently that addresses both of my current concerns.
Revealing Module Pattern
So in this example, I have no issues with event handlers, but I can't mock calls to functions
within functions to test in isolation:
var Lion = (function () {
// Reference to rawr works as expected when the click event is triggered
function watch() {
document.addEventListener('click', rawr);
}
function rawr() {
console.log('rawr');
}
function attack() {
console.log('attack');
}
/*
* Can't test goCrazy() in isolation. Mocking rawr() and attack()
* has no effect as demonstrated below.
*/
function goCrazy() {
rawr();
attack();
// Important "crazy" logic
}
return {
watch: watch,
rawr: rawr,
attack: attack,
goCrazy: goCrazy
};
}());
module.exports = Lion;
Example Test Case (Jasmine)
describe('Mock Check', function () {
it('should mock rawr() and attack() and test only goCrazy logic', function () {
var lion = require('Lion');
spyOn(lion, 'rawr').and.reutrnValue(true);
spyOn(lion, 'attack').and.reutrnValue(true);
var crazy = lion.goCrazy();
expect(lion.rawr).toHaveBeenCalled(); // <-- Fails
expect(lion.attack).toHaveBeenCalled(); // <-- Fails
// can't test goCrazy() logic in isolation :(
});
});
Same Module using this instead and invoked using new
In this example, I can successfully mock calls to functions within functions, but if I attempt to add an event handler, this becomes undefined when the event is triggered.
var Lion = function () {
// Reference to 'this' becomes undefined when event is triggered
this.watch = function () {
document.addEventListener('click', this.rawr);
}
this.rawr = function () {
console.log('rawr');
}
this.attack = function () {
console.log('attack');
}
/*
* Can successfully test goCrazy() in isolation by being able to mock
* rawr() and attack() as needed
*/
this.goCrazy = function () {
this.rawr();
this.attack();
// Important "crazy" logic
}
};
module.exports = Lion;
Example Test Case (Jasmine)
describe('Mock Check', function () {
it('should mock rawr() and attack() and test only goCrazy logic', function () {
var Lion = require('Lion');
var lion = new Lion();
spyOn(lion, 'rawr').and.reutrnValue(true);
spyOn(lion, 'attack').and.reutrnValue(true);
var crazy = lion.goCrazy();
expect(lion.rawr).toHaveBeenCalled(); // <-- Success
expect(lion.attack).toHaveBeenCalled(); // <-- Success
// testing goCrazy logic in isolation :)
});
});
Thanks for your time. If any clarification is necessary, let me know and I'll modify my post.
The actual problem here is that, the event handler loses the context of the current object. You can bind it like this
document.addEventListener('click', this.rawr.bind(this));
This will make sure that whenever the rawr is invoked, the this inside rawr corresponds to the lion object which you created.
It appears that my interval is never triggered.
I have a directive which contains a $interval and I want to test it. I've removed all the directive-related code and added this piece instead in its controller:
window.called = 0;
window.interval = $interval(function () {
window.called++;
console.log('interval ' + window.called); // 4
}, 10);
console.log('initialized'); // 1
The test looks like this:
describe('myDirective', function () {
beforeEach(module('myModule'));
beforeEach(function($compile, $rootScope) {
/* ... compile element in its own scope ... */
});
it('should run the interval', function () {
console.log(window.interval); // 2
waitsFor(function () {
console.log('tick'); // 3
return false;
}, 1000);
});
});
This is a dumb test. The waitsFor method actually returns false all the time, for debugging purposes. But this is all I see in the console:
initialized // 1
Object: {then: ..} // 2
tick // 3
tick // 3
tick // 3
tick // 3
..
and eventually the test failure. I never see a single interval in the logs. Is there something wrong with my code in general or is there something particular to Jasmine/PhantomJS that I'm missing?
$interval has a mock implementation in angular-mocks.
Make sure you are using a version of angular-mocks that matches your angular version.
The mock version of $interval has a flush method for controlling ticks.
See ngMock.$interval
See this fiddle with a demonstration:
//--- CODE --------------------------
angular.module('myModule', []).service('myModuleService', ['$interval', function ($interval) {
var called = 0;
$interval(function () {
called++;
}, 10);
this.getCalled = function () {
return called;
}
}]);
// --- SPECS -------------------------
describe('test $interval', function () {
it('calls the interval callback', function () {
var service, $interval;
angular.mock.module('myModule');
angular.mock.inject(function (myModuleService, _$interval_) {
// Initialize the service under test instance
service = myModuleService;
$interval = _$interval_;
});
expect(service.getCalled()).toEqual(0);
$interval.flush(11);
expect(service.getCalled()).toEqual(1);
$interval.flush(10);
expect(service.getCalled()).toEqual(2);
});
});
I am facing a situation where I need to add the same blocks of code to the start and the end of multiple functions in JavaScript. e.g.
function funcA () {
// code block 1
...
// code unique to funcA
...
// code block 2
...
}
function funcB () {
// code block 1
...
// code unique to funcB
...
// code block 2
...
}
function funcC () {
// code block 1
...
// code unique to funcC
...
// code block 2
...
}
I wonder what is the right pattern to use here to minimize the duplications.
Its called the extract method refactoring.
function block1()
{
// code block 1
}
function block2()
{
// code block 2
}
function funcA () {
block1();
// code unique to funcA
....
block2();
}
function funcB () {
block1();
// code unique to funcB
....
block2();
}
function funcC () {
block1();
// code unique to funcC
....
block2();
}
You could use another function to build your functions for you:
function makeFunc( specialProcessing ) {
return function() {
// block 1
specialProcessing( x, y, z );
// block 2
};
}
var func1 = makeFunc( function( x, y, z ) {
// stuff for func1
});
var func2 = makeFunc( function( x, y, z ) {
// stuff for func2
});
If you have sizable chunks of code in these blocks that can be applied to each function universally, by simply changing the variables in use, then you should extract those blocks of codes to separate methods. This has the advantage of promoting code reuse, improving readability of your code, and making it much, much easier to test and debug, particularly if you're following test-driven development ideals or even just running your own functional testing. It is always a goal of good software engineering and design to create small methods that are useful in many places to reduce the work you have to do and decrease the number of bugs in your code.
Blocks can be extracted to functions and called using the apply method. This will keep context and forward any arguments passed to original function.
function funcA() {
block1.apply(this, arguments);
// specific code to funcA
block2.apply(this, arguments);
}
arguments will contain any arguments passed to parent function
If you know it'll always be set up like that and you don't want to have the actual function calls inside of it, or maybe some will be in different orders I always like to set up a function to interwine the function calls for me.
jsFiddle DEMO
// Set up dynamically to handle calling any number of functions
// in whatever order they are specified in the parameters
// ie: setupFunctionOrder(func1, func2, func3, func4);
function setupFunctionOrder () {
for (i = 0; i < arguments.length; i++) {
arguments[i]();
}
}
function block1 () { log('\nblock1 - running'); }
function block2 () { log('block2 - running'); }
function funcA () { log('funcA - running'); }
// ** Useage:
// now we make the actual call to set up the ORDER of calling -funcA-
setupFunctionOrder(block1, funcA, block2);
Just pass in the function you want to be unique. Like this:
function reusableFunc(fn) {
//reused code block here
fn();
//reused code block here
}
var myResuableFunc1 = function (args) {
reusableFunc(function () {
//do your business here.
});
};
var myResuableFunc2 = function (args) {
reusableFunc(function () {
//do your business here.
});
};
//Or another way
function myResuableFunc3(args) {
reusableFunc(function () {
//do your business here
});
}
Then, you can create as many functions using the shared code as you want and, through the power of closures, pass these newly created functions around any way that you like.