Project Outline
Class Index | File Index
«
JsMockito - Mockito port to JavaScript

Class Index

_global_

Global namespace.

JsMockito

Contents

  1. Let's verify some behaviour!
  2. How about some stubbing?
  3. Matching Arguments
  4. Verifying exact number of invocations / at least once / never
  5. Matching the context ('this')
  6. Making sure interactions never happened on a mock
  7. Finding redundant invocations

In the following examples object mocking is done with Array as this is well understood, although you probably wouldn't mock this in normal test development.

1. Let's verify some behaviour!

For an object:

//mock creation
var mockedArray = mock(Array);

//using mock object
mockedArray.push("one");
mockedArray.reverse();

//verification
verify(mockedArray).push("one");
verify(mockedArray).reverse();

For a function:

//mock creation
var mockedFunc = mockFunction();

//using mock function
mockedFunc('hello world');
mockedFunc.call(this, 'foobar');
mockedFunc.apply(this, [ 'barfoo' ]);

//verification
verify(mockedFunc)('hello world');
verify(mockedFunc)('foobar');
verify(mockedFunc)('barfoo');

Once created a mock will remember all interactions. Then you selectively verify whatever interactions you are interested in.

2. How about some stubbing?

For an object:

var mockedArray = mock(Array);

//stubbing
when(mockedArray).slice(0).thenReturn('f');
when(mockedArray).slice(1).thenThrow('An exception');
when(mockedArray).slice(2).then(function() { return 1+2 });

//the following returns "f"
assertThat(mockedArray.slice(0), equalTo('f'));

//the following throws exception 'An exception'
var ex = undefined;
try {
  mockedArray.slice(1);
} catch (e) {
  ex = e;
}
assertThat(ex, equalTo('An exception');

//the following invokes the stub method, which returns 3
assertThat(mockedArray.slice(2), equalTo(3));

//the following returns undefined as slice(999) was not stubbed
assertThat(mockedArray.slice(999), typeOf('undefined'));

//stubs can take multiple values to return in order (same for 'thenThrow' and 'then' as well)
when(mockedArray).pop().thenReturn('a', 'b', 'c');
assertThat(mockedArray.pop(), equalTo('a'));
assertThat(mockedArray.pop(), equalTo('b'));
assertThat(mockedArray.pop(), equalTo('c'));
assertThat(mockedArray.pop(), equalTo('c'));

//stubs can also be chained to return values in order
when(mockedArray).unshift().thenReturn('a').thenReturn('b').then(function() { return 'c' });
assertThat(mockedArray.unshift(), equalTo('a'));
assertThat(mockedArray.unshift(), equalTo('b'));
assertThat(mockedArray.unshift(), equalTo('c'));
assertThat(mockedArray.unshift(), equalTo('c'));

//stub matching can overlap, allowing for specific cases and defaults
when(mockedArray).slice(3).thenReturn('abcde');
when(mockedArray).slice(3, lessThan(0)).thenReturn('edcba');
assertThat(mockedArray.slice(3, -1), equalTo('edcba'));
assertThat(mockedArray.slice(3, 1), equalTo('abcde'));
assertThat(mockedArray.slice(3), equalTo('abcde'));

//can also verify a stubbed invocation, although this is usually redundant
verify(mockedArray).slice(0);

For a function:

var mockedFunc = mockFunction();

//stubbing
when(mockedFunc)(0).thenReturn('f');
when(mockedFunc)(1).thenThrow('An exception');
when(mockedFunc)(2).then(function() { return 1+2 });

//the following returns "f"
assertThat(mockedFunc(0), equalTo('f'))

//following throws exception 'An exception'
mockedFunc(1);
//the following throws exception 'An exception'
var ex = undefined;
try {
  mockedFunc(1);
} catch (e) {
  ex = e;
}
assertThat(ex, equalTo('An exception');

//the following invokes the stub method, which returns 3
assertThat(mockedFunc(2), equalTo(3));

//following returns undefined as mockedFunc(999) was not stubbed
assertThat(mockedFunc(999), typeOf('undefined'));

//stubs can take multiple values to return in order (same for 'thenThrow' and 'then' as well)
when(mockedFunc)(3).thenReturn('a', 'b', 'c');
assertThat(mockedFunc(3), equalTo('a'));
assertThat(mockedFunc(3), equalTo('b'));
assertThat(mockedFunc(3), equalTo('c'));
assertThat(mockedFunc(3), equalTo('c'));

//stubs can also be chained to return values in order
when(mockedFunc)(4).thenReturn('a').thenReturn('b').then(function() { return 'c' });
assertThat(mockedFunc(4), equalTo('a'));
assertThat(mockedFunc(4), equalTo('b'));
assertThat(mockedFunc(4), equalTo('c'));
assertThat(mockedFunc(4), equalTo('c'));

//stub matching can overlap, allowing for specific cases and defaults
when(mockedFunc)(5).thenReturn('abcde')
when(mockedFunc)(5, lessThan(0)).thenReturn('edcba')
assertThat(mockedFunc(5, -1), equalTo('edcba'))
assertThat(mockedFunc(5, 1), equalTo('abcde'))
assertThat(mockedFunc(5), equalTo('abcde'))

//can also verify a stubbed invocation, although this is usually redundant
verify(mockedFunc)(0);
  • By default mocks return undefined from all invocations;
  • Stubs can be overwritten;
  • Once stubbed, the method will always return the stubbed value regardless of how many times it is called;
  • Last stubbing is more important - when you stubbed the same method with the same (or overlapping) matchers many times.

3. Matching Arguments

JsMockito verifies arguments using JsHamcrest matchers.

var mockedArray = mock(Array);
var mockedFunc = mockFunction();

//stubbing using JsHamcrest
when(mockedArray).slice(lessThan(10)).thenReturn('f');
when(mockedFunc)(containsString('world')).thenReturn('foobar');

//following returns "f"
mockedArray.slice(5);

//following returns "foobar"
mockedFunc('hello world');

//you can also use matchers in verification
verify(mockedArray).slice(greaterThan(4));
verify(mockedFunc)(equalTo('hello world'));

//if not specified then the matcher is anything(), thus either of these
//will match an invocation with a single argument
verify(mockedFunc)();
verify(mockedFunc)(anything());
  • If the argument provided during verification/stubbing is not a JsHamcrest matcher, then 'equalTo(arg)' is used instead;
  • Where a function/method was invoked with an argument, but the stub or verification does not provide a matcher, then anything() is assumed;
  • The reverse, however, is not true - the anything() matcher will not match an argument that was never provided.

4. Verifying exact number of invocations / at least once / never

var mockedArray = mock(Array);
var mockedFunc = mockFunction();

mockedArray.slice(5);
mockedArray.slice(6);
mockedFunc('a');
mockedFunc('b');

//verification of multiple matching invocations
verify(mockedArray, times(2)).slice(anything());
verify(mockedFunc, times(2))(anything());

//the default is times(1), making these are equivalent
verify(mockedArray, times(1)).slice(5);
verify(mockedArray).slice(5);

5. Matching the context ('this')

Functions can be invoked with a specific context, using the 'call' or 'apply' methods. JsMockito mock functions (and mock object methods) will remember this context and verification/stubbing can match on it.

For a function:

var mockedFunc = mockFunction();
var context1 = {};
var context2 = {};

when(mockedFunc).call(equalTo(context2), anything()).thenReturn('hello');

mockedFunc.call(context1, 'foo');
//the following returns 'hello'
mockedFunc.apply(context2, [ 'bar' ]);

verify(mockedFunc).apply(context1, [ 'foo' ]);
verify(mockedFunc).call(context2, 'bar');

For object method invocations, the context is usually the object itself. But sometimes people do strange things, and you need to test it - so the same approach can be used for an object:

var mockedArray = mock(Array);
var otherContext = {};

when(mockedArray).slice.call(otherContext, 5).thenReturn('h');

//the following returns 'h'
mockedArray.slice.apply(otherContext, [ 5 ]);

verify(mockedArray).slice.call(equalTo(otherContext), 5);
  • For mock functions, the default context matcher is anything();
  • For mock object methods, the default context matcher is sameAs(mockObj).

6. Making sure interactions never happened on a mock

var mockOne = mock(Array);
var mockTwo = mock(Array);
var mockThree = mockFunction();

//only mockOne is interacted with
mockOne.push(5);

//verify a method was never called
verify(mockOne, never()).unshift('a');

//verify that other mocks were not interacted with
verifyZeroInteractions(mockTwo, mockThree);

7. Finding redundant invocations

var mockArray = mock(Array);

mockArray.push(5);
mockArray.push(8);

verify(mockArray).push(5);

// following verification will fail
verifyNoMoreInteractions(mockArray);
Documentation generated by JsDoc Toolkit 2.1.0 on Tue Aug 16 2011 16:26:01 GMT+0200 (CEST)