Testing functions with expect()

Often, in tests, what we need is not only to enforce a function returned value (what Functions\when() allows to do), but to test function behavior based on expectations.

Mockery has a very powerful, and human readable Domain Specific Language (DSL) that allows to set expectations on how object methods should behave, e.g. validate arguments they should receive, how many times they are called, and so on.

Brain Monkey brings that power to function testing. The entry-point is the Functions\expect() function.

It receives a function name and returns a Mockery expectation object with all its power.

Below there are just several examples, for the full story about Mockery expectations see its documentation.

Only note that in functions testing the shouldReceive Mockery method makes no sense, so don't use it (an exception will be thrown if you do that).

Expectations on times a function is called

Functions\expect('paganini')->once();
Functions\expect('tween')->twice();
Functions\expect('who_knows')->zeroOrMoreTimes();
Functions\expect('i_should_run')->atLeast()->once();
Functions\expect('i_have_a_max')->atMost()->twice();
Functions\expect('poor_me')->never();
Functions\expect('pretty_precise')->times(3);
Functions\expect('i_have_max_and_min')->between(2, 4);

There is no need to explain how it works: Mockery DSL reads like plain English.

Of course, expectation on the times a function should run can be combined with arguments expectation.

Expectations on received arguments

Below a few examples, for the full story see Mockery docs.

// allow anything
Functions\expect('function_name')
->once()
->withAnyArgs();
// allow nothing
Functions\expect('function_name')
->once()
->withNoArgs();
// validate specific arguments
Functions\expect('function_name')
->once()
->with('arg_1', 'arg2');
// validate specific argument types
Functions\expect('function_name')
->times(3)
->with(Mockery::type('resource'), Mockery::type('int'));
// validate anything in specific places
Functions\expect('function_name')
->zeroOrMoreTimes()
->with(Mockery::any());
// validate a set of given arguments
Functions::expect('function_name')
->once()
->with(Mockery::anyOf('a', 'b', 'c'));
// regex validation
Functions\expect('function_name')
->once()
->with('/^foo/');
// excluding specific values
Functions\expect('function_name')
->once()
->with(Mockery::not(2, 3));
// dealing with array arguments
Functions\expect('function_name')
->once()
->with(Mockery::hasKey('foo'), Mockery::contains('bar', 'baz'));

Forcing behavior

Excluding shouldReceive, all the Mockery expectation methods can be used with Brain Monkey, including andReturn or andReturnUsing used to enforce a function to return specific values during tests.

In fact, Functions\when() do same thing for simple cases when no expectations are required.

Again, just a few examples:

// return a specific value
Functions\expect('function_name')
->once()
->with('foo', 'bar')
->andReturn('Baz!');
// return values in order
Functions\expect('function_name')
->twice()
->andReturn('First time I run', 'Second time I run');
// return values in order, alternative
Functions\expect('function_name')
->twice()
->andReturnValues(['First time I run', 'Second time I run']);
// return noting
Functions::expect('function_name')
->twice()
->andReturnNull();
// use a callback for returning a value
Functions\expect('function_name')
->atLeast()
->once()
->andReturnUsing(function() {
return 'I am an alias!';
});
// makes function throws an Exception (e.g. to test try statements)
Functions\expect('function_name')
->once()
->andThrow('RuntimeException'); // Both exception names and object are supported