Skip to content

Instantly share code, notes, and snippets.

@asgrim
Last active December 17, 2015 18:09
Show Gist options
  • Save asgrim/5650743 to your computer and use it in GitHub Desktop.
Save asgrim/5650743 to your computer and use it in GitHub Desktop.
<?php
abstract class AbstractController
{
public function dispatch($action)
{
$actionName = $action . "Action";
if (!method_exists($this, $actionName))
{
throw new Exception("Action method '{$actionName}' does not exist");
}
$this->$actionName();
}
}
<?php
require_once("src/AbstractController.php");
class AbstractControllerTest extends PHPUnit_Framework_TestCase
{
public function testDispatchWillDispatchActionRequest()
{
$controller = $this->getMockForAbstractClass('AbstractController', array(), '', true, true, true, array('indexAction'));
$controller->expects($this->once())->method('indexAction');
$controller->dispatch('index');
}
}
$ phpunit
PHPUnit 3.7.21 by Sebastian Bergmann.
Configuration read from /home/james/Workspace/methodtest/phpunit.xml
E
Time: 0 seconds, Memory: 3.25Mb
There was 1 error:
1) AbstractControllerTest::testDispatchWillDispatchActionRequest
Exception: Action method 'indexAction' does not exist
/home/james/Workspace/methodtest/src/AbstractController.php:11
/home/james/Workspace/methodtest/tests/AbstractControllerTest.php:13
/usr/share/php/PHPUnit/TextUI/Command.php:176
/usr/share/php/PHPUnit/TextUI/Command.php:129
FAILURES!
Tests: 1, Assertions: 0, Errors: 1.
@asgrim
Copy link
Author

asgrim commented May 25, 2013

The Problem
I want to test that my dispatch() method is calling a method (which doesn't exist within the context of the AbstractController class). Even if I tell PHPUnit to mock the method indexAction(), the method_exists() call will fail because the method.. doesn't exist :) How can I test this? How can I trick it into passing the method_exists() call?

@asgrim
Copy link
Author

asgrim commented May 25, 2013

The Solution
@benjie pointed out here that the $mockedMethods array is only added to $methods if it actually exists, unlike if you call $this->getMock() directly instead.

My workaround/solution is as follows:

// Remove this line:
$controller = $this->getMockForAbstractClass('AbstractController', array(), '', true, true, true, array('indexAction'));

// Add this line instead:
$controller = $this->getMock('AbstractController', array('indexAction'));

This only works because I haven't declared any abstract functions within my abstract class - if I did, I expect it would break, but I haven't tested so can't vouch for that assumption ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment