dpx86402 2015-02-11 10:22
浏览 56
已采纳

Symfony:测试自定义用户登录

Just recently I got into testing pieces of a symfony application... For starters, I thought I would try and test a login form that should grant access to a private area.

The users for this private area are correctly persisted to the database and have been tried on the development enviroment. The config_test.yml file goes like this:

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 

So it should use the database configuration exposed in config_dev.yml.

There's nothing special about my user provider:

providers:
    users:
        entity: 
            class: MyBundle:User
            property: login

As requested in the comments section, here's the security info. Please note that all namespaces, class names and relevant data have been changed, as I can't publish the real thing. If you spot any mistake it must have been me changing the relevant code.

security:
    encoders:
        MyBundle\Entity\User:
           algorithm: bcrypt
           cost: 12

    role_hierarchy:
        ROLE_CUSER:       ROLE_USER
        ROLE_CUSER_A: ROLE_CUSER
        ROLE_CUSER_B: ROLE_CUSER
        ROLE_CUSER_C: ROLE_CUSER
        ROLE_CUSER_D: ROLE_CUSER
        ROLE_CUSER_E: ROLE_CUSER

    providers:
        users:
            entity: 
                class: MyBundle:User
                property: login

    firewalls:
        dev:
            pattern:  ^/(_(profiler|wdt)|css|images|js)/
            security: false

        user_tools_login_firewall:
             pattern:   ^/user_tools/login$
             anonymous: ~
        user_tools:
             pattern: ^/user_tools
             http_basic: ~
             provider: users
             form_login:
                 login_path: /user_tools/login
                 check_path: /user_tools/login_check
             logout:
                 path: /user_tools/logout
                 target: /user_tools/home
                 invalidate_session: false

    access_control:
        - {path: /user_tools/login, roles: IS_AUTHENTICATED_ANONYMOUSLY}
        - {path: ^/user_tools/users/, roles: ROLE_CUSER_A}
        - {path: ^/user_tools/news/, roles: ROLE_CUSER_B}

Let's take a look at the testing unit...

class SecurityControllerTest extends WebTestCase
{
    const LOGIN_ERROR='this_is_a_non_existing_user';
    const PASS_ERROR='with_a_non_existing_pass';

    const LOGIN='this_is_a_valid_user';
    const PASS='with_a_valid_pass';
    const PASS_CRYPT='##and_this_is_the_encripted_pass_as_pasted_from_the_database##';

    const ID_SUBMIT='btn_submit';

    private $client;
    private $crawler;

    public function testIndex()
    {
        $this->client=static::createClient();
        $this->crawler=$this->client->request('GET', '/route_to_login');

        //Let's check that there are users in the database...
            $em=$this->client->getContainer()->get('doctrine')->getManager();
        $users=$em->getRepository("MyBundle:User")->findAll();
        $this->assertGreaterThan(0, count($users));

        //Now let's check that there's a valid user...
        $valid_user=$em->getRepository("MyBundle:User")->findBy(
            array('login' => self::LOGIN,
                'pass' => self::PASS_CRYPT));
        $this->assertGreaterThan(0, count($valid_user));

        //Let's check that there is no invalid user ;).
        $invalid_user=$em->getRepository("MyBundle:User")->findBy(
            array('login' => self::LOGIN_ERROR,
                'pass' => self::PASS_ERROR));
        $this->assertEquals(0, count($invalid_user));

        //The view should be the one I expect...
        $this->assertEquals('MyBundle\Controller\User\SecurityController::loginAction', $this->client->getRequest()->attributes->get('_controller'));

        //Let's try an invalid access...
        $this->form_login(self::LOGIN_ERROR, self::PASS_ERROR);
        $this->assertEquals('MyBundle\Controller\User\SecurityController::loginAction', $this->client->getRequest()->attributes->get('_controller'));

        //And now, let's try the good one!.
        self::form_login(self::LOGIN, self::PASS);
        $this->assertEquals('MyBundle\Controller\User\HomeController::homeAction', $this->client->getRequest()->attributes->get('_controller'));
    }

    private function form_login($login, $pass)
    {
        $form=$this->crawler->selectButton(self::ID_SUBMIT)->form();
        $form['_username']=$login;
        $form['_password']=$pass;
        $this->client->submit($form);
        $this->crawler=$this->client->followRedirect();
    }
}

The thing is, all tests are passed except the last one (that is, the good login). It does not go to the expected controller, but back to the login.

Here's the phpunit error:

There was 1 failure:

1) MyBundle\Tests\Controller\User\SecurityControllerTest::testIndex
Failed asserting that null matches expected 'MyBundle\Controller\User\HomeController::homeAction'.

Is there something I am missing here?. Everything is working as expected into the dev enviroment. Users do exists (and are asserted, as you can see). I am prepared to give more info as requested.

Thanks!.

  • 写回答

1条回答 默认 最新

  • duanrebo3559 2015-02-11 10:54
    关注

    You forgot to define the default_target_path in your form_login configuration, try to add your path like this:

             form_login:
                 login_path: /user_tools/login
                 check_path: /user_tools/login_check
                 default_target_path: your_target_path
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 BV260Y用MQTT向阿里云发布主题消息一直错误
  • ¥20 求个正点原子stm32f407开发版的贪吃蛇游戏
  • ¥15 划分vlan后,链路不通了?
  • ¥20 求各位懂行的人,注册表能不能看到usb使用得具体信息,干了什么,传输了什么数据
  • ¥15 Vue3 大型图片数据拖动排序
  • ¥15 Centos / PETGEM
  • ¥15 划分vlan后不通了
  • ¥20 用雷电模拟器安装百达屋apk一直闪退
  • ¥15 算能科技20240506咨询(拒绝大模型回答)
  • ¥15 自适应 AR 模型 参数估计Matlab程序