我正在使用Symfony和FOSUserBundle,现在我喜欢测试一些东西:
对于那些测试,我需要是特定用户或至少在用户组中。 如何模拟用户会话以便......
示例:
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.
}
}
答案 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_id
到session.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());