无法在自定义Laravel测试环境中进行身份验证(codeception)

时间:2014-10-13 03:16:04

标签: php authentication laravel codeception

我正在运行Vagrant(宅基地),PHP 5.5.12和Laravel 4.2。我试图配置代码以使用测试环境进行验收测试(在phantomJS上运行)。在宅基地上我有两个环境:本地和测试。我小心不要加倍默认的测试'环境,为PHPUnit测试保留。

我的问题是虽然我可以使用Eloquent来实例化用户(并检索它),但我无法对该用户进行任何测试的身份验证。这使我无法运行我的测试套件,其中90%需要用户身份验证。

我在/ etc / nginx / sites-available中定义了两个站点:myapp.app和myapp.test。我将fastcgi_param APP_ENV定义为本地和测试(分别)。我在〜/ .bashrc中也指定了APP_ENV,所以echo $ APP_ENV返回' local'。我创建了相应的config / test文件夹,其中包含指向测试数据库的database.php凭据。下面是默认的codeception.yml设置,以及被accept.suite.yml设置覆盖的设置(这是我专门运行的套件)。

我无法在测试环境中进行身份验证。所有这样做的尝试都返回false或null。

codeception.yml

actor: Tester
paths:
    tests: tests
    log: tests/_output
    data: tests/_data
    helpers: tests/_support
settings:
    bootstrap: _bootstrap.php
    colors: true
    memory_limit: 1024M
modules:
    config:
        Db:
            dsn: 'pgsql:host=localhost;dbname=myapp'
            user: 'myapp'
            password: 'myapp'
            dump: tests/_data/dump.sql

acceptance.suite.yml

class_name: AcceptanceTester
modules:
    enabled:
        - Laravel4
        - AcceptanceHelper
        - WebDriver
        - Db
    config:
        WebDriver:
            url: 'http://myapp.test'
            browser: phantomjs
            window_size: 1024x768
        Db:
            dsn: 'pgsql:host=localhost;dbname=myapp_testing'
            user: 'myapp_testing'
            password: 'myapp_testing'
            dump: tests/_data/test-dump.sql
            populate: true
            cleanup: false

这个接受帮助程序编译到AcceptanceTester类中,并在需要身份验证的所有Cests上的before过滤器中运行。我在这里测试了User :: create方法的输出,它确实创建了一个我可以访问的用户对象,例如,在login方法中。但是,它并没有出现在我的数据库中(从Navicat查看)。数据库当前是从test-dump.sql文件填充的,并且只包含没有任何数据的模式。我不确定为什么Eloquent创建方法不会写入数据库,但我最好的猜测是在测试套件运行后数据库正在回滚。

AcceptanceHelper.php

<?php namespace Codeception\Module;

// here you can define custom actions
// all public methods declared in helper class will be available in $I

use AcceptanceTester;
use Hash;
use LoginPage;
use User;

class AcceptanceHelper extends \Codeception\Module
{
    public function loginUser(AcceptanceTester $I)
    {
        User::create([
            'first_name' => 'test',
            'last_name' => 'test',
            'password' => Hash::make('1234'),
            'email' => 'test@test.com'
        ]);
        $this->login($I, 'test@test.com', '1234');
    }

    public function login(AcceptanceTester $I, $email, $password)
    {
        $I->amOnPage(LoginPage::$URL);
        $I->fillField('email', $email);
        $I->fillField('password', $password);
        $I->click(LoginPage::$loginButton);
        $I->see('Welcome. Your email address is test@test.com');
    }

    public function logoutUser(AcceptanceTester $I)
    {
        $I->amOnPage('/logout');
        $I->seeCurrentUrlEquals('/login');
        $I->see('You have been logged out');
    }
}

以下是会话控制器上的存储操作,该操作应该对用户进行身份验证(并且在myapp.app http请求的本地环境中工作正常)。对于myapp.test的登录尝试,Auth :: attempt方法返回false。

SessionsController.php

public function store()
{
    $this->loginForm->validate($input = Input::only('email', 'password'));

    if (Auth::attempt($input))
    {
        return Redirect::intended('profile')->with('flash_message', 'You have been logged in!');
    }

    return Redirect::back()->with('flash_message', 'Invalid credentials.')->withInput();
}

我直接拨入Auth :: attempt方法,该方法调用Auth / Guard-&gt; hasValidCredentials。

protected function hasValidCredentials($user, $credentials)
{
    return ! is_null($user) && $this->provider->validateCredentials($user, $credentials);
}

返回null。为了澄清,它甚至在调用$ user-&gt; first_name返回true后立即返回null,或者User :: all() - &gt; first() - &gt; first_name返回正确的名字。换句话说,我可以使用Eloquent创建然后检索用户,然后立即测试最终调用hasValidCredentials的Auth :: attempt,调用Eloquent / Builder-&gt;其中,根据登录的电子邮件地址查找form,并返回null。是否有可能将用户存储在内存中而不是数据库中?

我手动创建了一个用户并尝试手动验证,登录表单只是重新加载。我没有在本地&#39;中进行身份验证的问题。环境。

在身份验证期间调用以下方法,并返回包含null结果的查询对象。

Eloquent / Builder.php行:569

call_user_func_array(array($this->query, 'where'), func_get_args());

下面是我的UserCest.php文件。 BaseAcceptanceHelper仅调用AcceptanceTester-&gt;登录功能来验证默认测试用户。这失败了。

UserCest.php

use MyApp\Helpers\TestHelpers\BaseAcceptanceHelper;

class UserCest extends BaseAcceptanceHelper {

    public function _before(AcceptanceTester $I)
    {
        parent::_before($I);
    }

    public function _after()
    {
    }

    public function view_profile(AcceptanceTester $I)
    {
        $I->wantTo("view a user's profile");

        $I->amOnPage('users');

        NavBarComponent::goToMyProfile($I);

        $I->seeInCurrentUrl('profile');
    }

}

非常感谢任何帮助。我完全不知道为什么认证失败了。

1 个答案:

答案 0 :(得分:6)

解决方案是在acceptance.suite.yml中定义Laravel4模块的配置设置:

class_name: AcceptanceTester
modules:
    enabled:
        - Laravel4
        - AcceptanceHelper
        - WebDriver
        - Db
    config:
        Laravel4:
            cleanup: false
            environment: test
        WebDriver:
            url: 'http://myapp.test'
            browser: phantomjs
            window_size: 1024x768
        Db:
            dsn: 'pgsql:host=localhost;dbname=myapp_testing'
            user: 'myapp_testing'
            password: 'myapp_testing'
            dump: tests/_data/test-dump.sql
            populate: true
            cleanup: false

cleanup: true阻止在测试之间回滚db环境,environment: test告诉Laravel4使用正确的数据库。

我遇到的另一个问题是,我在发布时没有意识到,我的'test'环境文件夹已经复制了来自默认Laravel'测试'环境的cache.php和session.php配置文件,它将缓存和会话分配给内存数组。页面之间没有持久的会话数据,因此无法进行身份验证。我刚从config / test中删除了这两个文件,我很好。