php - Laravel phpunit 测试失败。转到意外的页面。只发生在测试中

标签 php laravel unit-testing laravel-5 phpunit

所以,我有一个页面,上面有一个按钮,值为“Create”。当我单击创建按钮时,没有填写任何字段,它会验证表单并在同一页面上显示错误消息。当我在浏览器中这样做时,它工作正常,但是当我用 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 View 的相关部分:

<?= 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查看和显示错误。但由于某种原因,它被踢到患者页面(这只发生在测试中,如果我通过手动单击浏览器中的“创建”按钮来尝试它,它会按预期工作)

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

最佳答案

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

当您使用 PHPUnit 进行测试时,不会发送该 token ,因此您要么必须自己发送它,要么必须从检查 token 的中间件中排除您的测试。排除测试是更简单的方法。

在 Laravel 5.0 中,我通过覆盖 VerifyCsrfToken 中间件中的 handle() 方法来做到这一点。

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 从 Laravel 站点根目录中的 phpunit.xml 文件中提取环境变量。 APP_ENV 变量是控制应用程序环境名称的变量,默认为“testing”。如果您的不同,则需要更改我提供的代码以匹配它。

关于php - Laravel phpunit 测试失败。转到意外的页面。只发生在测试中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35087810/

相关文章:

php - Laravel 8 + 捷流 : How to Redirect to Prior Page After Login?

java - 如何检查端点是否用于 munit 测试

c# - 如何模拟 IDataReader 以测试将 SqlDataReader 转换为 System.DataView 的方法

php - Laravel 和 phpMyAdmin - pdoexception 无法建立连接,因为目标机器主动拒绝它

php - 在 Activecollab 中按类别过滤项目

javascript - HTML 文本,为隐藏字段设置相同的值

php - 如何在 Laravel 中使用另一个字段进行身份验证?

php - 在 Android 应用程序中获取并显示单个用户的 MySQL 数据

php - 重定向两次到一个网站

javascript - Vue-test-utils 包装器未定义