سؤال

After a lot of research and without found nothing helpful I come here to see if can get some help. I'm building some functional tests for my code and one of those test need a fake user for work since in the function at controller I need to access to User object by using this piece of code:

$account = $this->getUser();
$user = $account->getUser();

This is the code in my test:

public function testmodifyCommissionAction() {
    $this->logIn();

    $updateCompanyCommission = $this->client->getContainer()->get('router')->generate('updateCompanyCommission', array(), false);
    $this->client->request("POST", $updateCompanyCommission, array(
        'id' => rand(1, 10),
        'fee' => rand(1, 10)
    ));

    var_dump($this->client->getResponse()->getContent());

    $this->assertSame(200, $this->client->getResponse()->getStatusCode()); // Test if response is OK
    $this->assertSame('application/json', $this->client->getResponse()->headers->get('Content-Type')); // Test if Content-Type is valid application/json
    $this->assertNotEmpty($this->client->getResponse()->getContent()); // Test that response is not empty

    $decoded = json_decode($this->client->getResponse()->getContent(), true);

}

private function logIn() {
    $session = $this->client->getContainer()->get('session');

    $firewall = 'secured_area';
    $token = new UsernamePasswordToken('admin', null, $firewall, array('ROLE_ADMIN'));
    $session->set('_security_' . $firewall, serialize($token));
    $session->save();

    $cookie = new Cookie($session->getName(), $session->getId());
    $this->client->getCookieJar()->set($cookie);
}

Now, where is the problem here? If I login in my application using valid credentials and run the test then I got this error:

Cannot set session ID after the session has started. (500 Internal Server Error)

If I logout and run the same test it works, so something is wrong here and I can't get what is, any help? advice? tips? example of working code?

EDIT: created User and try to login with the current created User

I modified a bit the method and now this is the current code I have:

protected function createUser() {
    $kernel = new \AppKernel('test', true);
    $kernel->boot();

    $this->container = $kernel->getContainer();
    $userManager = $this->container->get('fos_user.user_manager');
    $userManager->createUser();

    $data['firstname'] = $this->generateRandomString(4);
    $data['lastname'] = $this->generateRandomString(4);
    $data['lastname2'] = "";
    $data['photo'] = "";
    $data['banner'] = "";
    $data['password'] = md5($this->generateRandomString(18));
    $data['email'] = $this->generateRandomString(6) . "@test.com";

    $user = $userManager->createAccountAndUser($data);

    return $user;
}

This is the function I'm using to login, modified also to add support for current user:

private function logIn($client, $user) {
    $session = $client->getContainer()->get('session');

    $firewall = 'main';
    $token = new UsernamePasswordToken($user, null, $firewall, array('ROLE_USER'));
    $session->set('_security_' . $firewall, serialize($token));
    $session->save();

    $cookie = new Cookie($session->getName(), $session->getId());
    $client->getCookieJar()->set($cookie);
}

And this is the test I'm trying to run:

public function testmodifyCommissionAction() {
    $client = static::createClient();
    $user = $this->createUser();

    $this->logIn($client, $user->getUser()->getAlias());

    $updateCompanyCommission = $client->getContainer()->get('router')->generate('updateCompanyCommission', array(), false);
    $client->request("POST", $updateCompanyCommission, array(
        'id' => rand(1, 10),
        'fee' => rand(1, 10)
    ));

    $this->assertSame(200, $client->getResponse()->getStatusCode());
    $this->assertSame('application/json', $client->getResponse()->headers->get('Content-Type'));
    $this->assertNotEmpty($client->getResponse()->getContent());
}

But fails with this message:

PHP Fatal error:  Call to a member function getUser() on a non-object in /var/www/html/kraken/src/Wuelto/Company/ApprovalBundle/Controller/FeeCompanyController.php on line 47
PHP Stack trace:
PHP   1. {main}() /usr/bin/phpunit:0
PHP   2. PHPUnit_TextUI_Command::main() /usr/bin/phpunit:46
PHP   3. PHPUnit_TextUI_Command->run() /usr/share/pear/PHPUnit/TextUI/Command.php:129
PHP   4. PHPUnit_TextUI_TestRunner->doRun() /usr/share/pear/PHPUnit/TextUI/Command.php:176
PHP   5. PHPUnit_Framework_TestSuite->run() /usr/share/pear/PHPUnit/TextUI/TestRunner.php:349
PHP   6. PHPUnit_Framework_TestSuite->runTest() /usr/share/pear/PHPUnit/Framework/TestSuite.php:745
PHP   7. PHPUnit_Framework_TestCase->run() /usr/share/pear/PHPUnit/Framework/TestSuite.php:775
PHP   8. PHPUnit_Framework_TestResult->run() /usr/share/pear/PHPUnit/Framework/TestCase.php:783
PHP   9. PHPUnit_Framework_TestCase->runBare() /usr/share/pear/PHPUnit/Framework/TestResult.php:648
PHP  10. PHPUnit_Framework_TestCase->runTest() /usr/share/pear/PHPUnit/Framework/TestCase.php:838
PHP  11. ReflectionMethod->invokeArgs() /usr/share/pear/PHPUnit/Framework/TestCase.php:983
PHP  12. Wuelto\Company\ApprovalBundle\Tests\Controller\FeeCompanyControllerTest->testmodifyCommissionAction() /usr/share/pear/PHPUnit/Framework/TestCase.php:983
PHP  13. Symfony\Component\BrowserKit\Client->request() /var/www/html/kraken/src/Wuelto/Company/ApprovalBundle/Tests/Controller/FeeCompanyControllerTest.php:71
PHP  14. Symfony\Bundle\FrameworkBundle\Client->doRequest() /var/www/html/kraken/vendor/symfony/symfony/src/Symfony/Component/BrowserKit/Client.php:325
PHP  15. Symfony\Component\HttpKernel\Client->doRequest() /var/www/html/kraken/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Client.php:111
PHP  16. Symfony\Component\HttpKernel\Kernel->handle() /var/www/html/kraken/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Client.php:81
PHP  17. Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel->handle() /var/www/html/kraken/app/bootstrap.php.cache:2303
PHP  18. Symfony\Component\HttpKernel\HttpKernel->handle() /var/www/html/kraken/app/bootstrap.php.cache:3022
PHP  19. Symfony\Component\HttpKernel\HttpKernel->handleRaw() /var/www/html/kraken/app/bootstrap.php.cache:2883
PHP  20. call_user_func_array:{/var/www/html/kraken/app/bootstrap.php.cache:2911}() /var/www/html/kraken/app/bootstrap.php.cache:2911
PHP  21. Company\ApprovalBundle\Controller\FeeCompanyController->modifyCommissionAction() /var/www/html/kraken/app/bootstrap.php.cache:2911

I can't find where is the problem, any help?

Solution: The problem was on this line:

$this->logIn($client, $user->getUser()->getAlias());

since I was trying to pass $user->getUser()->getAlias() instead of $user the object.

EDIT 2: Sort code and getting error while trying to DELETE the recently test user

Now I made some changes and pass the $this->createUser() to setUp() function in order to have User object on $this->user var.

public function setUp() {
    static::$kernel = static::createKernel();
    static::$kernel->boot();
    $this->em = static::$kernel->getContainer()->get('doctrine')->getManager();

    $fixture = new LoadFeeData();
    $fixture->load($this->em);

    $this->user = $this->createUser();

    parent::setUp();
}

Now in tearDown() I'm trying to delete the current User I created earlier with this code:

protected function tearDown() {
    parent::tearDown();

    $this->em->remove($this->user);
    $this->em->flush();
    $this->em->close();
}

But get this error:

1) Company\ApprovalBundle\Tests\Controller\FeeCompanyControllerTest::testmodifyCommissionAction
Undefined index: 0000000065c988b30000000022bd0894

/var/www/html/kraken/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:2860
/var/www/html/kraken/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:1736
/var/www/html/kraken/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:1397
/var/www/html/kraken/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:1677
/var/www/html/kraken/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:1645
/var/www/html/kraken/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php:647
/var/www/html/kraken/app/cache/test/jms_diextra/doctrine/EntityManager_533ab9b6c8c69.php:59
/var/www/html/kraken/src/Company/ApprovalBundle/Tests/Controller/FeeCompanyControllerTest.php:131

Why I can't delete the User?

هل كانت مفيدة؟

المحلول

What I typically do is enable http_basic security for the test environment and then do the following to get an authenticated client:

config_test.yml

security:
    firewalls:
        wsse_secured: # This should be your firewall name
          http_basic: true

Next, make sure your tests extend the Symfony WebTestCase (Symfony\Bundle\FrameworkBundle\Test\WebTestCase)

Then you can just call:

$client = $this->createClient([], [
    'PHP_AUTH_USER' => $username,
    'PHP_AUTH_PW'   => $password,
]);

client->request("POST", $updateCompanyCommission, array(
    'id' => rand(1, 10),
    'fee' => rand(1, 10)
));

...

Using this method, the users need to either be loaded as a data fixture, or you can write a method to create a user in the setUp and destroy the user in the tearDown. Here is the method that I use to create a user for a test:

protected function createUser($password, $timezone, $roles)
{
    $kernel = new \AppKernel('test', true);
    $kernel->boot();

    /** @var Account $user */
    $this->container    = $kernel->getContainer();
    $userManager        = $this->container->get('fos_user.user_manager');
    $user               = $userManager->createUser();

    $user->setEmail('unique-email-address@not-here.com');
    $user->setUsername('auniqueusername');
    $user->setPlainPassword($password);
    $user->setTimezone($timezone);
    $user->setEnabled(true);

    foreach ($roles as $role) {
        $user->addRole($role);
    }

    $userManager->updateUser($user);

    return $user;
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top