Anyone who did unit testing in PHP knows that private methods are untestable. One workaround for this could be to make no private but protected only members and to call methods using a proxy class. Another approach I'd like to present here is a small extension hack.
C:
PHP_FUNCTION(publicize)
{
char *classname = NULL;
int classname_len;
ulong i;
char *str;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",
&classname, &classname_len) == FAILURE) {
return;
}
zend_class_entry **ce = NULL;
zend_hash_find(EG(class_table), classname, classname_len + 1, (void
**) &ce);
if(!ce) {
spprintf(&str, 0, "Class %s does not exist", classname);
zend_throw_exception(NULL, str, 0 TSRMLS_CC);
return;
}
HashTable *class_methods = &(*ce)->function_table;
if(class_methods && zend_hash_num_elements(class_methods) > 0) {
zend_hash_internal_pointer_reset(class_methods);
zend_function *method;
while(zend_hash_get_current_data(class_methods, (void **)
&method) == SUCCESS) {
method->common.fn_flags = method->common.fn_flags &
ZEND_ACC_PUBLIC;
zend_hash_move_forward(class_methods);
}
}
}
What it does in short - all private class methods get public. Assembling this small function as a simple extension you could use it like this:
PHP:
class c1 {
private $hello;
private function hello()
{
echo "i'm private hello from c1";
}
}
publicize('c1');
$c1 = new c1;
$c1->hello();
With a little additional hack one could also include class members publicizing.
Note, that rather like functionality might be available in PHP version 5.3.1 or newer, in earlier versions this approach could be used.
Links:
http://www.phpunit.de/
http://www.frontalaufprall.com/2007/11/16/testing-protected-methods-in-unit-tests/
http://news.php.net/php.internals/45448