Package a – javascript mocking framework

Me and Adlan Elmurzajev have just published https://npmjs.org/package/a – a javascript mocking framework for nodejs. It’s called a,  and is installed by npm . In addition to regular mocking, it can also stub require() – that means you can do proper unit testing by isolating the dependencies. The mocking framework can be used in any JavaScript testing framework.

(The package also has a unit test framework in bdd style – this is not fully documented yet, but you can find examples in  this repo: https://bitbucket.org/pure/a_demo . When the test framework is fully  documented, I will write a blog post about it.)

Key features

  • partial mock (fallback)
  • strict mock
  • mocking require()
  • object mock
  • multiple expects / returns
  • array expects
  • repeats: nTimes or infinite
  • verify
  • interceptors (whenCalled)

Mocking a function

partial mock

var original = function() {
    return 'realValue';
}

var mock = require('a').mock(original);
original = mock;
mock.expect().return('fake');

original(); //returns 'fake'
original(); //returns 'realValue'

strict mock

var original = function() {
    return 'realValue';
}

var mock = require('a').mock();
original = mock;
mock.expect().return('fake');

original(); //returns 'fake'
original(); //throws unexpected arguments

strict mock with arguments

var original = function(arg) {
    return 'realValue';
}

var mock = require('a').mock();
original = mock;
mock.expect('testValue1').return('fake1');
mock.expect('testValue2').return('fake2');

original('testValue1'); //returns 'fake1'
original('testValue2'); //returns 'fake2'
original(); //throws unexpected arguments
original('foo'); //throws unexpected arguments

strict mock with multiple arguments

var original = function(arg1, arg2) {
    return 'realValue';
}

var mock = require('a').mock();
original = mock;
mock.expect('firstArg1', 'secondArg1').return('fake1');
mock.expect('firstArg2', 'secondArg2').return('fake2');

original('firstArg1', 'secondArg1'); //returns 'fake1'
original('firstArg2', 'secondArg2'); //returns 'fake2'
original('foo'); //throws unexpected arguments
original('foo', 'bar'); //throws unexpected arguments

strict mock expecting array

var original = function(array) {
    return 'realValue';
}

var mock = require('a').mock();
original = mock;
mock.expectArray(['a','b']).return('fake1');
mock.expectArray(['a','b').return('fake2');
mock.expectArray(['c','d').return('fake3');

original(['a','b']); //returns 'fake1'
original(['a','b']); //returns 'fake2'
original(['c','d']); //returns 'fake3'
original(['a','b']); //throws unexpected arguments
original(['foo', 'bar']); //throws unexpected arguments

strict mock with repeats

var original = function() {
    return 'realValue';
}

var mock = require('a').mock();
original = mock;
mock.expect().return('fake').repeat(2);

original(); //returns 'fake'
original(); //returns 'fake'
original(); //throws unexpected arguments

strict mock with infinite repeats

var original = function() {
    return 'realValue';
}

var mock = require('a').mock();
original = mock;
mock.expect().return('fake').repeatAny();

original(); //returns 'fake'
original(); //returns 'fake'
original(); //returns 'fake'...

strict mock ignoring arguments

var original = function(arg) {
    return 'realValue';
}

var mock = require('a').mock();
original = mock;
mock.expectAnything().return('fake1');

original('someRandomValue'); //returns 'fake1'
original(); //throws unexpected arguments

strict mock with interceptor

var original = function(arg) {
    return 'realValue';
}

var mock = require('a').mock();
original = mock;
mock.expect('testValue').whenCalled(onCalled).return('fake1');

function onCalled(arg) {
    //arg == 'testValue'
}

original('testValue'); //returns 'fake1'
original(); //throws unexpected arguments

strict mock – verify (fail)

var original = function(arg) {
    return 'realValue';
}

var mock = require('a').mock();
original = mock;
mock.expect('testValue1').return('fake1');
mock.expect('testValue2').return('fake2');

original('testValue1'); //returns 'fake1'
mock.verify(); //throws mock has 1 pending functions

strict mock – verify (success)

var original = function(arg) {
    return 'realValue';
}

var mock = require('a').mock();
original = mock;
mock.expect('testValue1').return('fake1');
mock.expect('testValue2').return('fake2');

original('testValue1'); //returns 'fake1'
original('testValue2'); //returns 'fake2'
mock.verify(); //returns true

strict mock – advanced scenario

var original = function(arg, callback) {
    return 'realValue';
}

var mock = require('a').mock();
original = mock;
mock.expect('testValue').expectAnything().whenCalled(onCalled).return('fake1');

function onCalled(arg,callback) {
    //arg == 'testValue'
    //callback == foo
}

function foo() {    
}

original('testValue', foo); //returns 'fake1'
mock.verify() //returns true
original('testValue',foo); //throws unexpected arguments

Mocking require

expectRequire

var fakeDep = {};

var expectRequire = require('a').expectRequire;
expectRequire('./realDep').return(fakeDep);

require('./realDep'); //returns fakeDep
require('./realDep'); //returns realDep (behaves like a partial mock)

requireMock (compact syntax)

var requireMock = require('a').requireMock;
var fakeDep = requireMock('./realDep'); //returns a strict mock

require('./realDep'); //returns fakeDep
require('./realDep'); //returns realDep

..is equivalent to ..

var mock = require('a').mock();
var expectRequire = require('a').expectRequire;

var fakeDep = mock; 
expectRequire('./realDep').return(fakeDep);

require('./realDep'); //returns fakeDep
require('./realDep'); //returns realDep

Mocking an object

partial object mock

function newCustomer(_name) {
    var c = {};

    c.getName = function () 
    {
        return _name;
    };

    return c;
}

var customer = newCustomer('Alfonzo The Real');
var customerMock = mock(customer);

customerMock.getName.expect().return('Johnny Fake');

customer.getName(); //returns Johnny Fake
customer.getName(); //returns Alfonzo The Real
customerMock.verify(); //returns true
Advertisements
This entry was posted in code, javascript and tagged , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s