Unit Testing (PHPUnit): how to login?
-
05-07-2019 - |
Question
I'm writing tests for my current project, made with Zend Framework. Everything's fine, but I have a problem testing the logged users actions/controllers: I need to be logged in to be able to perform the action/controller.
How can I be logged in PHPUnit?
Solution
As you are saying you want to test actions/controllers, I suppose you are not writting unit-tests, but functional/integration tests -- ie, working with Zend_Test
and testing via the MVC.
Here is a test-function I used in a project, where I'm testing if logging in is OK :
public function testLoggingInShouldBeOk()
{
$this->dispatch('/login/login');
$csrf = $this->_getLoginFormCSRF();
$this->resetResponse();
$this->request->setPost(array(
'login' => 'LOGIN',
'password' => 'PASSWORD',
'csrfLogin' => $csrf,
'ok' => 'Login',
));
$this->request->setMethod('POST');
$this->dispatch('/login/login');
$this->assertRedirectTo('/');
$this->assertTrue(Zend_Auth::getInstance()->hasIdentity());
}
Simply : I'm loading the login form, extracting the CSRF token, populating the form, and posting it.
Then, I can test if I'm connected.
With that, you can probably extract the logging-in part, to call it before each one of your tests that require a valid user to be logged-in.
OTHER TIPS
There is another way. On my User
entity I have a login()
method that puts the user's id into the session and a static variable. What I just do in the test setUp()
is call $user->login()
and it works. In testing environment sessions are not used (setting Zend_Session::$isUnitTested = true
has this effect) and tests rely on the static variable. Just remember to clear the static variable (logout()
the user) on tearDown()
.
I think this article could help you: http://perevodik.net/en/posts/7/ It describes how to create a fake identity you can use to set the environment to a state equivalent to a user being logged in.
In much the same way Pascal is using this function:
$this->_getLoginFormCSRF();
I have created a generic function that returns the value by loading the form using the form element manager:
public function _getCSRFHashValueFromForm($formAlias, $csrfName) { $form = $this->servicemanager->get('FormElementManager')->get($formAlias); return $form->get($csrfName)->getValue(); }
This of course assumes that the CSRF is bound to the form and not within any fieldset etc.