ZF3 Модульный тест аутентификации на Bootstrap

У меня проблема с получением модульного теста для моего IndexController учебный класс.

Модульный тест просто делает следующее (вдохновленный модульное тестирование ZF3):

IndexControllerTest.php:

public function testIndexActionCanBeAccessed()
{
$this->dispatch('/', 'GET');
$this->assertResponseStatusCode(200);
$this->assertModuleName('main');
$this->assertControllerName(IndexController::class); // as specified in router's controller name alias
$this->assertControllerClass('IndexController');
$this->assertMatchedRouteName('main');
}

в Module.php У меня есть некоторые функции, чтобы проверить, если пользователь вошел в систему, иначе он будет перенаправлен на login маршрут.

Module.php:

public function onBootstrap(MvcEvent $mvcEvent)
{
/** @var AuthService $authService */
$authService = $mvcEvent->getApplication()->getServiceManager()->get(AuthService::class);
$this->auth = $authService->getAuth(); // returns the Zend AuthenticationService object

// store user and role in global viewmodel
if ($this->auth->hasIdentity()) {
$curUser = $this->auth->getIdentity();
$mvcEvent->getViewModel()->setVariable('curUser', $curUser['system_name']);
$mvcEvent->getViewModel()->setVariable('role', $curUser['role']);
$mvcEvent->getApplication()->getEventManager()->attach(MvcEvent::EVENT_ROUTE, [$this, 'checkPermission']);
} else {
$mvcEvent->getApplication()->getEventManager()->attach(MvcEvent::EVENT_DISPATCH, [$this, 'authRedirect'], 1000);
}
}

checkPermission Метод просто проверяет, находятся ли роль пользователя и соответствующий маршрут в хранилище acl.
Если это не удастся, я перенаправлю код состояния 404.

проблема: Модульный тест не пройден: «Не удалось подтвердить код ответа« 200 », фактический код состояния« 302 ». Поэтому модульный тест переходит в другой случай из моего onBootstrap метод в Module.php где редирект произойдет.

Я сделал следующее setUp в Прецедент но это не работает:

public function setUp()
{
// override default configuration values
$configOverrides = [];

$this->setApplicationConfig(ArrayUtils::merge(
include __DIR__ . '/../../../../config/application.config.php',
$configOverrides
));

$user = new Employee();
$user->id = 1;
$user->system_name = 'admin';
$user->role = 'Admin';

$this->authService = $this->prophesize(AuthService::class);
$auth = $this->prophesize(AuthenticationService::class);
$auth->hasIdentity()->willReturn(true);
$auth->getIdentity()->willReturn($user);

$this->authService->getAuth()->willReturn($auth->reveal());

$this->getApplicationServiceLocator()->setAllowOverride(true);
$this->getApplicationServiceLocator()->setService(AuthService::class, $this->authService->reveal());
$this->getApplicationServiceLocator()->setAllowOverride(false);

parent::setUp();
}

Советы очень ценятся

Код может немного отличаться от Zend Framework 2 но если у вас есть простой рабочий пример в zf2, возможно, я смогу преобразовать его в стиль zf3.

Я не использую ZfcUser — просто материал для Zend-Acl / Zend-аутентификации

2

Решение

После нескольких дней головной боли у меня есть рабочее решение.

Сначала я переместил весь код в onBootstrap Слушателю, потому что макеты phpunit генерируются после начальной загрузки zf и, следовательно, отсутствуют в моих модульных тестах.

Ключ заключается в том, что сервисы генерируются в моем методе вызываемого слушателя, который вызывается после завершения начальной загрузки zf.
Затем PHPUnit может переопределить службу с предоставленной имитацией.

AuthenticationListener

class AuthenticationListener implements ListenerAggregateInterface
{
use ListenerAggregateTrait;

/**
* @var AuthenticationService
*/
private $auth;

/**
* @var Acl
*/
private $acl;

/**
* Attach one or more listeners
*
* Implementors may add an optional $priority argument; the EventManager
* implementation will pass this to the aggregate.
*
* @param EventManagerInterface $events
* @param int $priority
*
* @return void
*/
public function attach(EventManagerInterface $events, $priority = 1)
{
$this->listeners[] = $events->attach(MvcEvent::EVENT_ROUTE, [$this, 'checkAuthentication']);
}

/**
* @param MvcEvent $event
*/
public function checkAuthentication($event)
{
$this->auth = $event->getApplication()->getServiceManager()->get(AuthenticationService::class);
$aclService = $event->getApplication()->getServiceManager()->get(AclService::class);
$this->acl = $aclService->init();

$event->getViewModel()->setVariable('acl', $this->acl);
if ($this->auth->hasIdentity()) {
$this->checkPermission($event);
} else {
$this->authRedirect($event);
}
}

// checkPermission & authRedirect method
}

Теперь мой onBootstrap стал действительно маленьким, как хочет ZF. ссылка на документацию

Module.php

public function onBootstrap(MvcEvent $event)
{
$authListener = new AuthenticationListener();
$authListener->attach($event->getApplication()->getEventManager());
}

Наконец мой издевательство в модульном тесте выглядит так:

IndexControllerTest

private function authMock()
{
$mockAuth = $this->getMockBuilder(AuthenticationService::class)->disableOriginalConstructor()->getMock();
$mockAuth->expects($this->any())->method('hasIdentity')->willReturn(true);
$mockAuth->expects($this->any())->method('getIdentity')->willReturn(['id' => 1, 'systemName' => 'admin', 'role' => 'Admin']);

$this->getApplicationServiceLocator()->setAllowOverride(true);
$this->getApplicationServiceLocator()->setService(AuthenticationService::class, $mockAuth);
$this->getApplicationServiceLocator()->setAllowOverride(false);
}
3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]