ZF2 модульное тестирование аутентификации
Я узнал о модульном тестировании и попытался решить следующую проблему:
Zend\ServiceManager\ServiceManager::get was unable to fetch or create an instance for zfcUserAuthentication
... используя единственный ответ, указанный на:
Простые модульные тесты ZF2 для контроллера с использованием ZfcUser
Так что моя функция setUp выглядит так же. К сожалению, я получаю сообщение об ошибке:
Zend\Mvc\Exception\InvalidPluginException: Plugin of type Mock_ZfcUserAuthentication_868bf824 is invalid; must implement Zend\Mvc\Controller\Plugin\PluginInterface
Это вызвано в этой части кода (разделено в моем коде таким же образом):
$this -> controller->getPluginManager()
->setService('zfcUserAuthentication', $authMock); // Error refers to this line.
Объект $authMock, очевидно, не реализует интерфейс plugin, который мне нужно реализовать, чтобы передать в setService.
Разве $authMock не предназначен для передачи его для использования в модульном тестировании? Должен ли я использовать другой (ориентированный на модульное тестирование) метод setService?
Мне нужен способ обработки входа в мое приложение, или мое модульное тестирование не имеет смысла.
Спасибо за любой совет.
=== Редактировать (11/02/2013) ===
Я хотел сосредоточиться на этой части для разъяснения, так как я думаю, что это проблемная область:
// Getting mock of authentication object, which is used as a plugin.
$authMock = $this->getMock('ZfcUser\Controller\Plugin\ZfcUserAuthentication');
// Some expectations of the authentication service.
$authMock -> expects($this->any())
-> method('hasIdentity')
-> will($this->returnValue(true));
$authMock -> expects($this->any())
-> method('getIdentity')
-> will($this->returnValue($ZfcUserMock));
// At this point, PluginManager disallows mock being assigned as plugin because
// it will not implement plugin interface, as mentioned.
$this -> controller->getPluginManager()
->setService('zfcUserAuthentication', $authMock);
Если макет не справляется с необходимыми реализациями, как еще мне притвориться, что зашел?
2 ответа
У вас проблема с пространством имен или вашим автозагрузчиком.
Когда вы создаете макет, определение класса ZfcUser\Controller\Plugin\ZfcUserAuthentication
не найден Поэтому PHPUnit создает макет, который расширяет этот класс только для вашего теста. Если класс был доступен, тогда PHPUnit будет использовать фактический класс для расширения при создании его макета, который затем будет использовать родительские классы / интерфейсы.
Вы можете увидеть эту логику здесь: https://github.com/sebastianbergmann/phpunit-mock-objects/blob/master/PHPUnit/Framework/MockObject/Generator.php
if (!class_exists($mockClassName['fullClassName'], $callAutoload) &&
!interface_exists($mockClassName['fullClassName'], $callAutoload)) {
$prologue = 'class ' . $mockClassName['originalClassName'] . "\n{\n}\n\n";
if (!empty($mockClassName['namespaceName'])) {
$prologue = 'namespace ' . $mockClassName['namespaceName'] .
" {\n\n" . $prologue . "}\n\n" .
"namespace {\n\n";
$epilogue = "\n\n}";
}
$cloneTemplate = new Text_Template(
$templateDir . 'mocked_clone.tpl'
);
Таким образом, если нет класса или интерфейса, PHPUnit фактически создаст его сам, чтобы макет соответствовал подсказке типа исходного имени класса. Однако любые родительские классы или интерфейсы не будут включены, потому что PHPUnit не знает о них.
Это может быть связано с тем, что в тесте не указано правильное пространство имен, или в автозагрузчике возникла проблема. Трудно сказать, не видя весь тестовый файл.
Альтернативно, а не издеваться ZfcUser\Controller\Plugin\ZfcUserAuthentication
глядишь Zend\Mvc\Controller\Plugin\PluginInterface
в вашем тесте и передать это в менеджер плагинов. Хотя, если вы намекаете на тип для плагина в вашем коде, ваш тест все равно не будет работать.
//Mock the plugin interface for checking authorization
$authMock = $this->getMock('Zend\Mvc\Controller\Plugin\PluginInterface');
// Some expectations of the authentication service.
$authMock -> expects($this->any())
-> method('hasIdentity')
-> will($this->returnValue(true));
$authMock -> expects($this->any())
-> method('getIdentity')
-> will($this->returnValue($ZfcUserMock));
$this -> controller->getPluginManager()
->setService('zfcUserAuthentication', $authMock);
Я только что сделал пример для плагина FlashMessenger. Вам просто нужно использовать ControllerPluginManager для переопределения ControllerPlugin. Убедитесь, что ваше приложение загружает вызовы setApplicationConfig ();
<?php
namespace SimpleTest\Controller;
use Zend\Test\PHPUnit\Controller\AbstractHttpControllerTestCase;
class SimpleControllerTest extends AbstractHttpControllerTestCase {
public function testControllerWillAddErrorMessageToFlashMessenger()
{
$flashMessengerMock = $this->getMockBuilder('\Zend\Mvc\Controller\Plugin\FlashMessenger', array('addErrorMessage'))->getMock();
$flashMessengerMock->expects($this->once())
->method('addErrorMessage')
->will($this->returnValue(array()));
$serviceManager = $this->getApplicationServiceLocator();
$serviceManager->setAllowOverride(true);
$serviceManager->get('ControllerPluginManager')->setService('flashMessenger', $flashMessengerMock);
$this->dispatch('/error/message');
}
}?>