FOSUserBundle - PHPUnit - 模拟用户 - 无用户提供者

FOSUserBundle - PHPUnit - Mock a user - No User Provider

我正在将 Symfony 3.2 与 FOSUserBundle 一起使用,我正在尝试为需要在特定角色中进行身份验证的功能编写功能测试。

我使用了@tftd here 发布的方法,但是当我 运行 进行 phpunit 测试时,出现 500 错误:There is no user provider for user "Symfony\Component\Security\Core\User\User".

我的 webTestCase class 看起来像这样:

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);
                $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 = 'main'; // 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;
    }

我的测试例程如下所示:

class TryoutAdminControllerTest extends CustomWebTestCase
{
    public function testTryoutListAction()
    {
        $authenticatedClient = self::createAuthenticatedClient(array('ROLE_USER'));
        $crawler = $authenticatedClient->request('GET', '/admin/tryout');
        $this->assertEquals(302, $authenticatedClient->getResponse()->getStatusCode(), 'No access allowed!');

        $authorizedClient = self::createAuthenticatedClient(array('ROLE_ADMIN'));
        $crawler = $authorizedClient->request('GET', '/admin/tryout');
        $this->assertEquals(200, $authorizedClient->getResponse()->getStatusCode(), 'Access granted!');
    }
}

security.yml:

security:
    encoders:
        FOS\UserBundle\Model\UserInterface: bcrypt

    role_hierarchy:
        ROLE_ADMIN:       ROLE_USER
        ROLE_SUPER_ADMIN: ROLE_ADMIN

    providers:
        fos_userbundle:
            id: fos_user.user_provider.username

    firewalls:
        main:
            pattern: ^/
            form_login:
                provider: fos_userbundle
                csrf_token_generator: security.csrf.token_manager

            logout:       true
            anonymous:    true
            switch_user:  true
            remember_me:
                secret:   '%secret%'
                lifetime: 604800 # 1 week in seconds
                path:     /
                domain:   ~
                user_provider: fos_userbundle

最后 config_test.yml

imports:
    - { resource: config_dev.yml }

framework:
    test: ~
    session:
        storage_id: session.storage.mock_file
    profiler:
        collect: false

web_profiler:
    toolbar: false
    intercept_redirects: false

swiftmailer:
    disable_delivery: true

如果有人能告诉我我遗漏了什么,我将不胜感激!

您可能需要在 WebTestCase 中实例化您自己的用户 class,它从 FOS\UserBundle\Model\User 而不是 Symfony\Component\Security\Core\User\User 扩展,因为您使用的是 FosUserBundle 用户提供程序。

考虑使用测试数据库和数据装置,因为您可能需要它来进行功能测试。 LiipFunctionalTestBundle 可能会有帮助。

请记住,正如问题标题中所建议的那样,此测试中没有模拟任何内容。必须在单元测试中使用模拟,而不是在功能测试中使用。