Mock

You can create a Mock object, expect methods to be called, and verify that they were called. You can also stub a method to always return a specified value. Just like you do in Ruby.

Minitest.js also comes with the ability to spy on given methods and verify if they were called or called with a set of arguments.

Usage

Node.js

var Mock = require('minitest/mock');
var stub = require('minitest/stub');
var spy  = require('minitest/spy');

Browser

You can create global shortcuts:

<script src="minitest-mock.js"></script>
<script src="minitest-stub.js"></script>
<script src="minitest-spy.js"></script>
<script>
var Mock = minitest.Mock;
var stub = minitest.stub;
var spy  = minitest.spy;
</script>

API

constructor

First you need to create a Mock object. That can't go any simpler:

var obj = new Mock();

.expect(methodName, [returnValue])

Once you have a Mock object, you can expect methods to be called and return a value —if you omit a return value, the method will simply return undefined.

obj.expect('meaning_of_life', 42);
obj.meaning_of_life();  // => 42

If you expect multiple calls to the same method, you must tell the mock object, otherwise you'll eventually get a MockExpectationError. Calls to the same method are executed in the order they are defined:

obj.expect('foo', 'bar');
obj.expect('foo', 'baz');

obj.foo();  // => 'bar'
obj.foo();  // => 'baz'
obj.foo();  // => throws a MockExpectationError: unexpected call to foo.

Of course you can expect different calls to different methods. The actual calls don't have to be in order.

obj.expect('getFoo', 'foo');
obj.expect('getBar', 'bar');

obj.getBar();  // => 'bar'
obj.getFoo();  // => 'foo'

.expect(methodName, returnValue, args = [])

You can also specify arguments that must match the actual calls:

obj.expect('sum', 3, [1, 2]);
obj.expect('sum', 4, [1, 3]);

obj.sum(1, 2);  // => 3
obj.sum(2, 3);  // => throws a MockExpectationError: wrong arguments.

Arguments can either be strict (eg: a number or a string) or loose (eg: a class name), so you may validate the type of arguments, instead of their actual value:

obj.expect('foo', null, [Number, String]);
obj.foo(123, "str");

.expect(methodName, returnValue, callback)

You may prefer or need to validate the arguments manually:

obj.expect('foo', null, function (arg1, arg2) {
    return arg1 < 10 && arg2 > 10;
});

obj.foo(3, 12);

.verify()

Eventually you can verify that all calls were made with the verify() method:

var obj = new Mock();
obj.expect('foo', null);
obj.foo();
obj.verify();  // => true

But if an expected call isn't fulfilled a MockExpectationError will be thrown:

var obj = new Mock();
obj.expect('foo', null);
obj.expect('meaning_of_life', 42);

obj.meaning_of_life();
obj.verify();  // => throws MockExpectationError: expected call to foo().

Stub

stub(object, methodName, returnValue, callback)

Stubs a method on object to always return a given value for the duration of the callback. The previous behavior of the method will be restored after the callback has returned.

stub(Date, 'now', 0, function () {
    Date.now();  // => 0
});

Date.now();  // => 1378647728279

object.stub(methodName, returnValue, callback)

On modern engines (see Spec for the list of supported browsers) the .stub() method is available directly as a non enumerable property on Object.prototype:

var obj = {
    test: function () { return true; }
};

obj.stub('test', false, function () {
    obj.test();  // => false
});

obj.test();  // => true

Spy

A spy is a noop function that does and returns nothing, but which you can verify that it was called. Thus is different from a stub, because a stub doesn't have to be verified.

spy(methodName)

Creates a spy method. The name will only be used in assertions, and the spy will do nothing.

assert.called(spy, msg)

Verifies that the spy was actually called.

var test = spy('test');
refute.called(test);

test();
assert.called(test);

This assertion is also available for specs (mustHaveBeenCalled) and expect (toHaveBeenCalled).

assert.calledWith(spy, args, msg)

Verifies that the spy was called with the given set of arguments.

var test = spy('test');
test(1, 2, 3);
assert.calledWith(test, [1, 2, 3]);
refute.calledWith(test, [4, 5, 6]);

This assertion is also available for specs (mustHaveBeenCalledWith) and expect (toHaveBeenCalledWith).

object.spy(methodName)

Spies on an object method. Convenience access for the above spy method.

var obj = {
    test: function () {}
};
obj.spy('test');

obj.test(1, 2, 3);
assert.called(obj.test);
assert.calledWith(obj.test, [1, 2, 3]);