Using PHPUnit 3.6 I'm trying to test the exec()
method in the below controller class. This method does two things:
The (simplified) source code looks like this:
abstract class CLIController extends Controller
{
/* irrelevant class details here */
public function exec()
{
$action = ! empty($this->opts->args[0])
? $this->opts->args[0]
: $this->default_action;
if ( ! $action || ! is_callable(array($this, $action))) {
$msg = 'Invalid controller action specified';
throw new LogicException($msg);
} else {
$this->$action(); // <---- trying to get code coverage on this line!
}
}
}
I can't figure out how to get coverage on this part of the code:
} else {
$this->$action();
}
because I'm not sure how to (or that it's even possible to) test the invocation of a method whose name is not known in the context of the abstract class. Again: the method to be called is declared in child classes. Normally I would just mock an abstract method but I can't in this case because the method doesn't exist yet -- it will be specified by a child class.
exec()
throws an exception when it's supposed to, I know that correct functioning of the line in question depends on PHP functioning correctly. Does this invalidate the need to test it in the first place ???exec()
function on their own. I would really appreciate any guidance on how best to proceed here. Thanks in advance.
I disagree with your stipulation that "it's [not] a good idea to create a concrete child class just to test an abstract parent." I do this quite often when testing abstract classes and usually name the concrete subclass after the test to make it clear.
class CLIControllerTest extends PHPUnit_Framework_TestCase
{
public function testCallsActionMethod()
{
$controller = new CLIControllerTest_WithActionMethod(...);
// set $controller->opts->args[0] to 'action'
$controller->exec();
self::assertTrue($controller->called, 'Action method was called');
}
}
class CLIControllerTest_WithActionMethod extends CLIController
{
public $called = false;
public function action() {
$this->called = true;
}
}
The code to make this test happen is trivial and can be easily verified by inspection.
I'm curious, why use is_callable
instead of method_exists
to avoid creating the array? It's probably just personal preference, but I'm wondering if there are any semantic differences.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With