-
Notifications
You must be signed in to change notification settings - Fork 48
Mocking
Google JS Test has a capable mocking system built in and accessible from any test. It is modeled on Google's C++ mocking framework, and should be familiar for anybody who has used that tool before, but can easily be picked up by beginners too.
Create mock functions using createMockFunction
:
var func = createMockFunction();
Create an instance of MyClass
with every function in its prototype replaced by
a mock function using createMockInstance
:
var instance = createMockInstance(MyClass);
Expect a call to a mock function func
to be made with particular arguments
like in the following examples:
// func should be called once with the argument 'taco'.
expectCall(func)('taco');
// Func should be called twice, each time with an arugment matching the given
// regular expression.
expectCall(func)(containsRegExp(/nice.*burrito/))
.times(2);
These expectations are automatically verified at the end of the currently running test, and will cause it to fail if they are not satisfied. Additionally, it will fail if a call not matching a registered expectation is received, or if a registered expectation is matched too many times.
Note the following:
-
If you give a value instead of a matcher, an implicit
equals
matcher is used, as with the'taco'
argument. -
If you don't use a
.times()
expression, the expectation has an implicit cardinality of one. (Actions can affect this; see below.)
By default a mock function does nothing and returns nothing (i.e. undefined
)
when it is called. You can add actions that will be performed when an
expectation is matched as in the following example:
expectCall(func)('taco')
.willOnce(returnWith(2));
expectCall(func)('burrito')
.willOnce(function() { [...] })
.willOnce(function() { [...] })
.willRepeatedly(returnWith(3));
expectCall(func)('queso')
.times(2)
.willRepeatedly(returnWith(4));
func('burrito'); // Invokes first function above
func('burrito'); // Invokes second function above
func('taco'); // Returns 2
func('taco'); // Causes unexpected call failure
func('burrito'); // Returns 3
func('burrito'); // Returns 3
func('queso'); // Returns 4
func('queso'); // Returns 4
func('queso'); // Causes unexpected call failure
As demonstrated above, the following modifiers are available:
-
times(n)
– Expect that this call will be matched exactlyn
times. -
willOnce(f)
– Set up an actionf
that is only performed once. You may list multiple such actions, and they are performed in order as the mock function is called. -
willRepeatedly(f)
– Set up a fallback actionf
that is invoked repeatedly after any.willOnce()
actions have been exhausted.
An action is simply a function. You may used the built-in returnWith
and
doAll
, or supply your own function. The function is passed the arguments given
to the mock function, and whatever it returns (if anything) is returned by the
mock function.
The rules for cardinality with regard to actions are as follows:
-
If an explicit cardinality
N
is set with.times(N)
, then anything other thanN
matching calls will cause a test failure. -
Otherwise, if there are any one-time actions set up, then it is expected there will be at least that many matching calls. If there is not also a fallback action, then it is expected that there will be exactly that many.
-
Otherwise, if there is a fallback action, any number of matching calls (including zero) is allowed.
-
Otherwise, the implicit expected count is one.
When a mock function receives a call, its expectations are evaluated from most recent to least recent. The idea is that at a beginning of a test, you can set up more general or default actions, and later you can set more specific ones relevant to the current test alone. For example:
expectCall(func)(_)
.willRepeatedly(returnWith(2));
expectCall(func)('taco')
.willOnce(returnWith(3))
.willOnce(returnWith(5));
func('burrito'); // Returns 2
func('taco')); // Returns 3
func('taco')); // Returns 5
func('taco')); // Causes 'too many calls' failure; the most recent match is already exhausted