Laravel phpunit测试失败了。去意想不到的页面。只在测试中发生

时间:2016-01-29 15:14:09

标签: php laravel unit-testing laravel-5 phpunit

所以,我有一个页面上有一个按钮,其值为#34;创建"。当我单击“创建”按钮而不填写任何字段时,它会验证表单并在同一页面上显示错误消息。当我在浏览器中执行此操作时,它工作正常,但当我使用phpunit时,它会产生意外结果,我不知道为什么。

这是我的集成测试:

public function testCreateValidation()                                     
{ 
    $this->visit(route('patients.indexes.create', $this->patient->id));    
    $this->press('Create');                                                
    $this->seePageIs(route('patients.indexes.create', $this->patient->id));              
}   

这就是结果:

There was 1 failure:
1) Tests\Integration\IndexControllerTest::testCreateValidation
Did not land on expected page [http://localhost/patients/69/indexes/create].

Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'http://localhost/patients/69/indexes/create'
+'http://localhost/patients'

/vagrant/vendor/laravel/framework/src/Illuminate/Foundation/Testing/InteractsWithPages.php:141
/vagrant/tests/Integration/IndexControllerTest.php:51

我不明白为什么会将其重定向到patients页面。

以下是正在测试的Laravel create方法:

public function create($id)                                                         
{                                                                                   
    $index = $this->indexes->newInstance();                                         
    $patient = $this->patients->findOrFail($id);                                    

    return view('patient.index.create', ['index' => $index, 'patient' => $patient]);
} 

以下是create观点的相关部分:

<?= Form::open(['route' => array('patients.indexes.store', $patient->id), 'class' => 'form-horizontal']) ?>
    @include('patient.index._form')
    <?= Form::submit('Create', ['class' => 'btn btn-primary']) ?>
<?= Form::close() ?> 

最后发送给它的store方法:

public function store(IndexRequest $request, $id)       
{                                                       
    $index = $this->indexes->newInstance();             
    $index->fill($request->all());                      
    $index->patient_id = $id;                           
    $index->save();                                     

    $patient = $index->patient;                         

    return redirect()->route('patients.edit', $patient);
} 

我也使用FormRequest来验证输入:

public function rules()                   
{                                         
    return [                              
        'index_title' => 'required',      
        'index_description' => 'required',
    ];                                    
}  

基本上,由于IndexRequest中的验证失败,IndexRequest应该将其重新启动到patients.indexes.create视图并显示错误。但由于某些原因,它被踢到患者页面(这只发生在测试中,如果我通过手动点击浏览器中的“创建”按钮进行尝试,它会按预期工作)

我以前遇到过这个问题,但从来没有能够解决它。有什么想法吗?

2 个答案:

答案 0 :(得分:4)

听起来你有CSRF个问题。当您在浏览器中导航到表单时,Laravel会在浏览器的Cookie和请求标头中存储special token。然后,当您提交表单时,它会查找该令牌以确保您是提交表单的人。

使用PHPUnit进行测试时,该令牌未被发送,因此您必须自己发送,或者必须从检查令牌的中间件中排除测试。排除测试是一种更简单的方法。

在Laravel 5.0中,我通过覆盖VerifyCsrfToken中间件中的class VerifyCsrfToken extends BaseVerifier { // Override the handle() method in the BaseVerifier class public function handle($request, Closure $next) { // When the App environment is 'testing', skip CSRF validation. if (app()->environment() === 'testing') { return $next($request); } return parent::handle($request, $next); } } 方法来做到这一点。

phpunit.xml

默认情况下,PHPUnit从Laravel站点根目录中的APP_ENV文件中提取环境变量。 it("Component should call componentWillReceiveProps on update", () => { const spy = sinon.spy(Component.prototype, "componentWillReceiveProps"); const wrapper = shallow(<Component {...props} />); expect(spy.calledOnce).to.equal(false); wrapper.setProps({ prop: 2 }); expect(spy.calledOnce).to.equal(true); }); 变量是控制应用程序环境名称的变量,默认为&#39; testing&#39;。如果你的不同,那么你需要更改我提供的代码以匹配它。

答案 1 :(得分:1)

如果中间件实际上是问题,您可以使用WithoutMiddleware特性将其从测试中排除:

class IndexControllerTest extends TestCase
{
    use Illuminate\Foundation\Testing\WithoutMiddleware;
    ...