如何在 Laravel 中测试 POST 路由

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28790348/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 11:02:32  来源:igfitidea点击:

How to test POST routes in Laravel

phplaravelphpunit

提问by Martyn

I'm doing the following to test a POST call to Laravel. I'm expecting that POST to questions, in accordance with my routes, will be dispatches as the store action method. This works in the browser.

我正在执行以下操作来测试对 Laravel 的 POST 调用。我期待根据我的路线对问题的 POST 将作为商店操作方法进行调度。这在浏览器中有效。

My test:

我的测试:

public function setUp()
    {   
        parent::setUp();

        Session::start();
    }

    public function testStoreAction()
    {
        $response = $this->call('POST', 'questions', array(
            '_token' => csrf_token(),
        ));

        $this->assertRedirectedTo('questions');
    }

However, I tells me that the redirect doesn't match. Also, I can see that it isn't going to the store action method at all. I want to know what action method it is going to, and why it isn't going to the store method (if I look at route:list I can see there is a POST questions/ route that should go to questions.store; this also works in the browser, but not in my tests). Also, am I writing the call correctly for this resource? I added the token here as it was throwing an exception as it should, in some tests I will let the token check pass.

但是,我告诉我重定向不匹配。此外,我可以看到它根本不会转到 store 操作方法。我想知道它将使用什么操作方法,以及为什么它不使用 store 方法(如果我查看 route:list,我可以看到有一个 POST questions/ route 应该转到 questions.store;这个也适用于浏览器,但不适用于我的测试)。另外,我是否正确地为此资源编写了调用?我在这里添加了令牌,因为它应该抛出异常,在某些测试中,我会让令牌检查通过。

回答by Daniel Ojeda

You could try this:

你可以试试这个:

public function testStoreAction()
{
    Session::start();
    $response = $this->call('POST', 'questions', array(
        '_token' => csrf_token(),
    ));
    $this->assertEquals(302, $response->getStatusCode());
    $this->assertRedirectedTo('questions');
}

回答by Raviraj Chauhan

The most recommended way to test your routes is to check for 200response. This is very helpful when you have multiple tests, like you are checking all of your postroutes at once.

测试路由的最推荐方法是检查200响应。当您进行多项测试时,这非常有用,例如post一次检查所有路线。

To do so, just use:

为此,只需使用:

public function testStoreAction()
{
    $response = $this->call('POST', 'questions', array(
        '_token' => csrf_token(),
    ));

    $this->assertEquals(200, $response->getStatusCode());
}

回答by Apit John Ismail

I use

我用

$response->assertSessionHasErrors(['key'=>'error-message']);

in order to assert validation works. But to use this, you must start from the page that is going to send the post request. Like this:

为了断言验证工作。但是要使用它,您必须从将要发送 post 请求的页面开始。像这样:

$user = User::where('name','Ahmad')->first(); //you can use factory. I never use factory while testing because it is slow. I only use factory to feed my database and migrate to make all my test faster.
$this->actingAs($user)->get('/user/create'); //This part is missing from most who get errors "key errors is missing"
$response = $this->post('/user/store', [
                '_token' => csrf_token()
            ]);
//If you use custom error message, you can add as array value as below.
$response->assertSessionHasErrors(['name' => 'Name is required. Cannot be empty']);
$response->assertSessionHasErrors(['email' => 'Email is required. Make sure key in correct email']);

Then if you want to test that the errors also being displayed correctly back. Run again above test with some changes as per below:

然后,如果您想测试错误是否也正确显示回来。再次运行上面的测试,并按照以下进行一些更改:

$this->actingAs($user)->get('/user/create'); 
$response = $this->followingRedirects()->post('/user/store', [
                '_token' => csrf_token()
            ]); //Add followingRedirects()
$response->assertSeeText('Name is required. Cannot be empty');
$response->assertSeeText('Email is required. Make sure key in correct email');

My guess is that if you dont start with the page to show the error, (the create / update page where you put the form), chain of session during the process will miss some important keys.

我的猜测是,如果您不从显示错误的页面开始(您放置表单的创建/更新页面),则在此过程中的会话链将错过一些重要的键。

回答by Gjaa

I was getting a TokenMismatchExceptionand this fixed it, maybe it helps you too

我得到了一个TokenMismatchException,这个修复了它,也许它对你也有帮助

public function testStoreAction()
{
    $response = $this->withSession(['_token' => 'covfefe'])
        ->post('questions', [
            '_token' => 'covfefe',
        ));

    $this->assertRedirectedTo('questions');
}

回答by Kumaravel K

Laravel Unit cases without middleware

没有中间件的 Laravel 单元案例

    use WithoutMiddleware;

    protected $candidate = false;

    public function setUp(): void
    {
        parent::setUp();        

        $this->candidate = new Candidate();
    }   

    /** @test */
    public function it_can_get_job_list()
    {
        $this->actingAs($this->user, 'api');

        $response = $this->candidate->getJobsList();

        $this->assertNotNull($response);

        $this->assertArrayHasKey('data', $response->toArray());

        $this->assertNotEmpty($response);

        $this->assertInternalType('object', $response);
    }