====== Mocking Functions in Simple Test ======
When dealing with external projects that you either want to re-use parts of or refactor, being able to write unit tests is often a big problem, especially if it's written in procedural code like;
function aFunctionIWantToTest($foo) {
$foo = aFunctionIDontWantToTest($foo);
}
function aFunctionIDontWantToTest($foo) {
global $conf; // aaargh!
if ( $conf['reevaluateMeEveryTime'] ) {
doSomethingPainful($foo);
} else {
ohGodAndAnotherFunction($foo);
}
}
Being able to "mock" ''aFunctionIDontWantToTest'' in a similar manner to [[http://www.lastcraft.com/mock_objects_documentation.php|Mock Objects]] would be a big help.
Brought this up a while back [[http://sourceforge.net/tracker/index.php?func=detail&aid=1315670&group_id=76550&atid=547458|here on the SimpleTest feature tracker]] and sent a [[http://sourceforge.net/mailarchive/forum.php?thread_id=8853618&forum_id=34779|mail today]] to the SimpleTest list with an initial implementation.((Note I'm //not// dumping this here to add pressure to include this in SimpleTest - there are good reasons why SimpleTest shouldn't offer this which I can understand - but not sure if the message to list included my attachment plus think this is a valid "unsupported" addition to SimpleTest which people can use at their own risk)).
After discovering [[http://www.php.net/apd|APD's]] (at least in the old 0.4 version I was using) [[phpfn>rename_function]] does very wierd things settled on [[http://www.php.net/runit|runkit]] as the tool to help "mock" a function, which so far seems to work fine. Be warned you can rename //anything// including pre-defined PHP functions - lots to room to shoot yourself in the foot.
Example use (testing [[http://dev.splitbrain.org/reference/dokuwiki/nav.html?inc/html.php.source.html#l284|this]]);
class html_hilight_test extends UnitTestCase {
function testHighlightTwoWords() {
MockFunction::generate('unslash');
$html = 'Foo bar Foo php Foo';
MockFunction::setReturnValueAt(0,'unslash','bar');
MockFunction::setReturnValueAt(1,'unslash','php');
MockFunction::expectCallCount('unslash',4);
$this->assertPattern(
'/Foo bar<\/span> Foo php<\/span> Foo/',
html_hilight($html,'bar php')
);
MockFunction::restore('unslash');
}
}
Basically the methods are all the same as normal SimpleTest mock objects but are called statically via the the MockFunction class.
**Note:** you must call ''MockFunction::restore()'' yourself when you're finished, otherwise you'll have mock functions "lying around", which may lead to //very// hard to debug problems when running other tests
Source code available here: {{develop:mockfunctions.tar.gz}}