Behat,Symfony 2和FOS用户:如何创建登录测试

时间:2015-09-07 10:45:39

标签: php symfony fosuserbundle behat

我是Behat的新手,我想创建一个功能来验证登录表单。我正在使用FOS用户包。

最简单的方法是执行以下操作:

When I am on "/login"
And I fill in "username" with "admin"
And I fill in "password" with "1234"
And I press "_submit"
Then I should be on "/dashboard"

期望用户“admin”存在于具有1234密码的数据库中。但我很确定必须有一种方法来模拟数据库或为FOS创建一个假用户。我一直在谷歌搜索,但找不到任何具体的东西。

理想情况下,我认为它应该像

Given there's a user "admin" with password "1234"
[rest of the test]

有什么想法吗?谢谢!

2 个答案:

答案 0 :(得分:3)

您可以定义登录的特定步骤,并在不同的测试中重复使用它。您甚至不需要密码,通过令牌模拟验证。

例如:

/**
 * @Given /^I am authenticated as "([^"]*)"$/
 */
public function iAmAuthenticatedAs($username)
{
    $driver = $this->getSession()->getDriver();
    if (!$driver instanceof BrowserKitDriver) {
        throw new UnsupportedDriverActionException('This step is only supported by the BrowserKitDriver');
    }

    $client = $driver->getClient();
    $client->getCookieJar()->set(new Cookie(session_name(), true));

    $session = $client->getContainer()->get('session');

    $user = $this->kernel->getContainer()->get('fos_user.user_manager')->findUserByUsername($username);
    $providerKey = $this->kernel->getContainer()->getParameter('fos_user.firewall_name');

    $token = new UsernamePasswordToken($user, null, $providerKey, $user->getRoles());
    $session->set('_security_'.$providerKey, serialize($token));
    $session->save();

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

然后用以下方法调用这一新步骤:

Scenario: Displaying the blog overview
Given I am authenticated as "bar"
  And I am on "/admin/"
 Then I should see "Admin dashboard"

实用内容:

答案 1 :(得分:0)

要验证FOSUserBundle登录表单,您可以编写此功能

Feature: Admin authentication
  In order to gain access to my admin management area
  As an admin
  I need to be able to login

  Scenario: Logging in
    Given there is an admin user "admin" with password "1234"
    And I am on "/login"
    When I fill in "Username" with "admin"
    And I fill in "Password" with "1234"
    And I press "Log in"
    Then I should see "Connected" //or anything that proves you're connected

然后您可以在FeatureContext.php中创建步骤验证,如下所示:

/**
 * @Given there is an admin user :username with password :password
 */
public function thereIsAnAdminUserWithPassword($username, $password)
{   // Create an Admin User
    $user = new \AppBundle\Entity\User();// inherits form FOSUserBundle\Entity\User()
    $user->setUsername($username);
    $user->setPlainPassword($password);
    $user->setEmail("example@mail.com");// required by FOSUserBundle
    $user->setEnabled(true); // add it manually otherwise you'll get "Account is disabled" error
    $user->setRoles(array('ROLE_ADMIN'));

    // Then you must store it in your database
}

问题是FeatureContext.php无法访问容器和实体管理器,如果您没有明确声明,则无法将用户存储在数据库中。最简单的方法是使用behat / symfony2-extension,然后只有您能够使用实体管理器并存储管理员用户。如果您正在使用Composer,那么您可以:

composer require --dev behat/symfony2-extension

然后你必须在behat.yml中激活扩展名,如下所示:

default:
# ...
    extensions:
        Behat\Symfony2Extension: ~

只有这样,您才能使FeatureContext.php知道容器,以便它可以访问实体管理器。将它添加到FeatureContext类中,如下所示:

class FeatureContext extends RawMinkContext implements Context, SnippetAcceptingContext
    {
        use \Behat\Symfony2Extension\Context\KernelDictionary;
    ...
    }

现在您可以调用实体管理器并存储您的管理员用户:

/**
 * @Given there is an admin user :username with password :password
 */
public function thereIsAnAdminUserWithPassword($username, $password)
{   // Create an Admin User
    $user = new \AppBundle\Entity\User();
    $user->setUsername($username);
    $user->setPlainPassword($password);
    $user->setEmail("example@mail.com");
    $user->setRoles(array('ROLE_ADMIN'));
    $user->setEnabled(true); 

    // Store it in the database
    $em = $this->getContainer()->get('doctrine')->getManager();
    $em->persist($user);
    $em->flush();
}

现在你可以使用你的测试了!不要忘记在启动测试之前清理数据库,否则在第二次尝试时你会得到一个很好的错误,说这个用户已经存在!最好的方法是添加一个clearData()函数,该函数在每个场景之前启动,如下所示:

/**
 * @BeforeScenario
 */
public function clearData()
{
    $em = $this->getContainer()->get('doctrine')->getManager();
    $em->createQuery('DELETE FROM AppBundle:User')->execute();
}
祝你好运!