FOSUserBundle - PHPUnit - 模拟用户

时间:2016-02-22 22:27:20

标签: symfony doctrine phpunit fosuserbundle symfony3.x

我正在使用Symfony和FOSUserBundle,现在我喜欢测试一些东西:

  • Doctrine lifecycle
  • 防火墙后面的控制器

对于那些测试,我需要是特定用户或至少在用户组中。 如何模拟用户会话以便......

  • “createdAt”等生命周期字段将使用登录用户
  • 控制器就像一些模拟用户登录

示例:

class FooTest extends ... {
    function setUp() {
        $user = $this->getMock('User', ['getId', 'getName']);

        $someWhereGlobal->user = $user;

        // after this you should be logged in as a mocked user
        // all operations should run using this user.
    }
}

3 个答案:

答案 0 :(得分:2)

在这种情况下,我要做的是创建一个扩展Symfony CustomWebTestCase的{​​{1}}。在类中,我将创建一个为我进行身份验证的方法。

以下是一个示例代码:

WebTestCase

上面的代码将直接创建一个有效的用户会话,并完全跳过防火墙。因此,您可以创建所需的任何namespace Company\MyBundle\Classes; use Symfony\Bundle\FrameworkBundle\Client; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\BrowserKit\Cookie; use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Security\Core\User\User; abstract class CustomWebTestCase extends WebTestCase { /** * @param array|null $roles * @return \Symfony\Bundle\FrameworkBundle\Client */ protected static function createAuthenticatedClient(array $roles = null) { // Assign default user roles if no roles have been passed. if($roles == null) { $role = new Role('ROLE_SUPER_ADMIN'); $roles = array($role); } else { $tmpRoles = array(); foreach($roles as $role) { $role = new Role($role, $role); $tmpRoles[] = $role; } $roles = $tmpRoles; } $user = new User('test_super_admin', 'passwd', $roles); return self::createAuthentication(static::createClient(), $user); } private static function createAuthentication(Client $client, User $user) { // Read below regarding config_test.yml! $session = $client->getContainer()->get('session'); // Authenticate $firewall = 'user_area'; // This MUST MATCH the name in your security.firewalls.->user_area<- $token = new UsernamePasswordToken($user, null, $firewall, $user->getRoles()); $session->set('_security_'.$firewall, serialize($token)); $session->save(); // Save authentication $cookie = new Cookie($session->getName(), $session->getId()); $client->getCookieJar()->set($cookie); return $client; } } ,它仍然有效。代码的重要部分位于方法$user中。这就是认证魔术。

还有一件事值得一提 - 确保您已在createAuthentication中设置framework.session.storage_idsession.storage.mock_file,以便Symfony会自动模拟会话,而不是您必须在每个测试中处理情况下:

config_test.yml

现在,在您的测试用例中,您只需扩展framework: session: storage_id: session.storage.mock_file 并调用MyWebTestCase方法:

createAuthenticatedClient()

您也可以在Symfony official documentation中看到一个示例。

答案 1 :(得分:2)

您可以使用LiipFunctionalTestBundle执行此操作。一旦安装并配置了Bundle,就可以轻松创建和用户并登录测试。

为您的用户创建一个灯具

这将创建一个将在测试期间加载的用户:

<?php
// Filename: DataFixtures/ORM/LoadUserData.php

namespace Acme\MyBundle\DataFixtures\ORM;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Acme\MyBundle\Entity\User;

class LoadUserData extends AbstractFixture implements FixtureInterface
{
    public function load(ObjectManager $manager)
    {
        $user = new User();
        $user
            ->setId(1)
            ->setName('foo bar')
            ->setEmail('foo@bar.com')
            ->setPassword('12341234')
            ->setAlgorithm('plaintext')
            ->setEnabled(true)
            ->setConfirmationToken(null)
        ;
        $manager->persist($user);
        $manager->flush();

        // Create a reference for this user.
        $this->addReference('user', $user);
    }
}

如果您想使用用户组,可以看到official documentation

以此用户身份登录测试

LiipFunctionalTestBundle's documentation中所述,以下是如何在数据库中加载用户并以此用户身份登录:

/**
 * Log in as the user defined in the Data Fixture.
 */
public function testWithUserLoggedIn()
{
    $fixtures = $this->loadFixtures(array(
        'Acme\MyBundle\DataFixtures\ORM\LoadUserData',
    ));

    $repository = $fixtures->getReferenceRepository();

    // Get the user from its reference.
    $user = $repository->getReference('user')

    // You can perform operations on this user.
    // ...

    // And perform functional tests:

    // Create a new Client which will be logged in.
    $this->loginAs($user, 'YOUR_FIREWALL_NAME');
    $this->client = static::makeClient();

    // The user is logged in: do whatever you want.
    $path = '/';
    $crawler = $this->client->request('GET', $path);
}

答案 2 :(得分:1)

您可以使用LiipFunctionalTestBundle轻松完成此操作,它可以为您创建单元测试的快捷方式。

如果您已经拥有用于创建或编辑的表单用户,则可以将其用于应用程序中的测试单元工作流用户:

使用makeClient方法记录测试

$credentials = array(
    'username' => 'a valid username',
    'password' => 'a valid password'
);

$client = static::makeClient($credentials);

使用您的表单测试您的创作

$crawler = $client->request('GET', '/profile');

$form = $crawler->selectButton('adding')->form();
$form['fos_user_profile_form[firstName]'] = 'Toto';
$form['fos_user_profile_form[lastName]'] = 'Tata';
$form['fos_user_profile_form[username]'] = 'dfgdgdgdgf';
$form['fos_user_profile_form[email]'] = 'testfgdf@grgreger.fr';
$form['fos_user_profile_form[current_password]'] = 'gfgfgdgpk5dfgddf';

测试&#34; createdAt&#34;只需在存储库用户中调用findOneBy就像这样

$user = $this->getObjectManager()
             ->getRepository('AcmeSecurityBundle:User')
             ->findOneBy(array('username' => 'testCreateUserUsername'));

$this->assertTrue($user->getCreatedAt() == now());