This is an idea for creating mocks for functions that could be disrupted by
events in the real world, events like database connectivity or some other IO.
The mocks should call the original function everywhere except during testing.
The following is an example code snippet that uses variable_get
, which
would be thoroughly disrupted if it could not connect to the database.
function my_function() {
$my_var = variable_get('my_var');
// Do something with my_var ...
}
There's no easy way to test my_function
without a database,
because variable_get
needs the database. One way around this is to
allow passing variable_get
as an argument:
function my_function($variable_get = 'variable_get') {
$my_var = $variable_get('my_var');
// Do something with my_var ...
}
Then all that is required to test my_function
is to pass a stub
for variable_get
. The usual callers of my_function
will be using the original variable_get
, but tests can call
my_module_function('mock_variable_get')
.
To prepare $mock_variable_get, we would need to create a function and use it like:
function mock_variable_get() {
// Simulate the database response
}
my_function('mock_variable_get');
This is not ideal: different tests may want to mock variable get with differing responses. A better solution is to prepare the mock along with the test that uses it. Something like this:
$mock_variable_get = new MockFunction::generate('variable_get');
$mock_variable_get->setReturnValue(
'Some value for my_var',
array('my_var')
);
Then we can call my_function
and pass it the MockFunction object.
$mock_variable_get = new MockFunction::generate('variable_get');
$mock_variable_get->setReturnValue(
'Some value for my_var',
array('my_var')
);
my_function($mock_variable_get);
We can also use the mock as a critic by preparing it to expect to receive a specific set of arguments:
$mock_variable_get->expectOnce(array('some obnoxious arg'));
my_function($mock_variable_get); // Assertion fails here