Laravel 4控制器测试 - 在过多$ this-> call()后出现ErrorException - 为什么?

时间:2013-07-07 19:35:48

标签: testing controller phpunit laravel laravel-4

我非常感谢有关我正在经历的Laravel 4问题的一些帮助。

我正在测试控制器路由,特别是负责路由问卷调查的控制器。我正在测试以下场景:用户试图跳过问题,用户请求不存在的问题......等等。

我为所有场景编写的测试到目前为止使用PHPunit按预期工作。我目前正在编写的测试涉及多个$this->call()$this->client->request()执行,这就是事情发生的地方。如果我在一个测试方法中执行$this->call()$this->client->request()太多次(特定于2个或更多),我会在终端中获得ErrorException:

  

{“error”:{“type”:“ErrorException”,“message”:“Undefined variable:header”,“file”:“/ Volumes / Dev HD / dmh / app / views / layouts / steps.php ”, “行”:1}}

如果我将测试方法中的$this->call()$this->client->request()的数量减少为1,则可以正常工作,并且不会显示任何异常。我一直在使用以下代码:

代码

/**
 * When the user skips questions they have not yet answered, the user 
 * should be redirected back to the first unanswered question.
 *
 * @return void
 */
public function testDiscoverSkipQuestions()
{
    // Get the first question.
    $domCrawler = $this->client->request('GET', 'style/discover');

    // Answer the first question
    $form = $domCrawler->selectButton("Next »")->form();
    $form['question_1'] = 'A:0';
    $response = $this->client->submit($form);
    $this->assertRedirectedTo('style/discover/2');

    // Get the 5th question.
    $this->call('GET', 'style/discover/5');
    // BROKEN

    // Expect to be redirected to the 2nd question.
    $this->assertRedirectedTo('style/discover/2');
    $this->assertSessionHas('attention');
}

有什么想法吗?

我是否需要重置某些内容才能拨打多个电话?做这样的几个电话这是不好的做法吗?有没有更好的方法来编写这个测试?任何想法都将不胜感激。

非常感谢!

1 个答案:

答案 0 :(得分:14)

可能的解决方案:

使用$this->client->restart()开始新请求。

说明/详情:

好的,这是兔子洞:D

  1. Laravel TestCase扩展Illuminate\Foundation\Testing\TestCase
  2. Illuminate\Foundation\Testing\TestCase使用Illuminate\Foundation\Testing\Client制作虚假请求。
  3. Illuminate\Foundation\Testing\Client扩展Symfony\Component\HttpKernel\Client
  4. Symfony\Component\HttpKernel\Client扩展了抽象类Symfony\Component\BrowserKit\ Client
  5. 抽象类Symfony\Component\BrowserKit\ Client有一个方法restart()
  6. 所以,我相信你的情况(我没有亲自测试过这个),你应该能够做到以下几点:

    /**
     * When the user skips questions they have not yet answered, the user 
     * should be redirected back to the first unanswered question.
     *
     * @return void
     */
    public function testDiscoverSkipQuestions()
    {
        // Get the first question.
        $domCrawler = $this->client->request('GET', 'style/discover');
    
        // Answer the first question
        $form = $domCrawler->selectButton("Next »")->form();
        $form['question_1'] = 'A:0';
        $response = $this->client->submit($form);
        $this->assertRedirectedTo('style/discover/2');
    
        // ******** Restart for new request ********
        $this->client->restart();
    
        // Get the 5th question.
        $this->call('GET', 'style/discover/5');
        // ******** SHOULD NOW WORK - call() is a proxy to $this->client->request(); ********
    
        // Expect to be redirected to the 2nd question.
        $this->assertRedirectedTo('style/discover/2');
        $this->assertSessionHas('attention');
    }
    

    注意,call()方法为a proxy to using $this->client->request()

    希望有所帮助!不要害怕深入挖掘代码继承,看看是否存在一种方便的方法来做你需要的 - 通常已经存在的变化:D

    改善(?)

    请注意,这些测试可能更倾向于“集成测试”而不是“单元测试”。与持续集成框架一起使用时,集成测试可能更适合。有关详细信息,请参阅this question