To fake out resources when unittesting, you can now [1] use the runkit PHP extension, which adds some more dynamism to PHP, you get to:
- add methods,
- redefine classes runtime,
- or run code in safe sandboxes
PHP heroine Sara Golemon created runkit, enabling this madness. (See her PECL user page for more of her Open Source contributions.)
My use-case for runkit+Unit Testing is Class Posing. [2]
When you deal with several layers of code, and you have no sensing in underlying layers, you feel the need to redefine that expensive database call, network access, or whatever’s cramping your unittesting style.
Fake resources using runkit ninja powers
- Create a test case for your class class
- Find a method that uses a hard-to-fake resource (some static method (Sklar explains why it’s hard), perhaps an irritating singleton).
Example test-case:
function testCallDbBadlyShouldComplain() { // This function body pacifies new DbQuery($cmd) $body = "return array();"; runkit_method_redefine( 'DbQuery', '__construct', '$cmd', $body); $ret = db_exec_command('foo', 'baz'); $this->assertEquals( array('alert'=>'Unknown DB command foo'), $ret); }
(Sorry for “hamburger example”, not real code.) For details, see runkit_method_redefine‘s manual page.
Uh, OK, that’s it, I think. I’ll try to be more PHPUnit-bloggy, as we go along. I like that tool.
Weak-ass disclaimer: In other situations, Dependency Injection, or some other dependency-breaking technique, chould be used. This case is for getting any coverage on legacy code. Think of it as just another technique, for your exotic toolchest.
[1] Why now? My ticket at PHPUnit‘s Trac got fixed, and is set to be released rather soon, in version 3.2.7. Sebastian Bergmann, main PHPUnit hacker, works hard, releases very often. So, either run trunk, or fix the little problem yourself, OR wait until next release.
[2]: About Class Posing: It was Sebastian Bergmann‘s idea to use it with PHPUnit. (He has a specialized chunk of C code sitting around on his desk, customized to extend PHP with Class Posing, but he has not [yet] gotten it into PECL, the extension repository.)
Leave a comment