1

我是 Laravel 和 IoC 概念的新手。我正在关注 Nettuts 上的精彩教程(http://net.tutsplus.com/tutorials/php/testing-laravel-controllers/)并且能够成功测试我的控制器。但是我想通过模拟数据库来隔离控制器。一旦我尝试将我的模拟对象注入到 IoC 中,我就会收到以下错误:

无法修改标头信息 - 标头已发送(输出开始于 /Users/STRATTON/Dev/SafeHaven/vendor/phpunit/phpunit/PHPUnit/Util/Printer.php:172)

它所指的行使用“打印”构造输出 PHPUnit 的缓冲区。某些东西导致在设置标头之前发送输出,但我无法找到问题所在。

当控制器调用真实模型并进行数据库调用时,我能够成功运行所有测试。同时,我能够成功地模拟对象并毫无错误地进行模拟。但是,一旦我尝试使用 App::instance() 注入模拟对象,就会出现错误。

我还用 PHPUnit 的模拟测试了这个并得到了相同的结果。我是否正确地模拟了对象?我有命名空间的问题吗?我错过了输出内容的东西吗?

控制器:

<?php namespace App\Controllers;

use App\Models\Repositories\ArticleRepositoryInterface;

class HomeController extends BaseController {

    protected $articles;

    public function __construct(ArticleRepositoryInterface $articles) 
    {
        $this->articles = $articles;
    }

    public function index()
    {
        $articles = $this->articles->recent();
        return \View::make('home.index')
            ->with('articles', $articles);
    }

}

测试用例

<?php namespace Tests\Controllers;

class HomeControllerTest extends \TestCase {

    public function testIndex()
    {
        $mocked = \Mockery::mock('App\\Models\\Repositories\\ArticleRepositoryInterface');
        $mocked->shouldReceive('recent')->once()->andReturn('foo');
        \App::instance('App\\Models\\Repositories\\ArticleRepositoryInterface', $mocked);
        //$mocked->recent();

        $this->call('GET', '/');
        $this->assertResponseOk();
        $this->assertViewHas('articles');
    }

}
4

2 回答 2

1

它实际上是一个关于在运行测试用例期间如何处理异常的错误,但是已经修复了,只需运行 composer update。

于 2013-05-18T08:17:28.300 回答
0

回答我自己的问题 - 错误的原因是代码的某些部分导致 PHP 错误或抛出异常。

在这种情况下,问题是从视图中抛出的异常。View 期望方法 recent() 返回的值是一个 Eloquent 集合(Illuminate\Database\Eloquent\Collection),或者至少是 View 可以迭代的东西。

HomeControllerTest::TestIndex 方法正在模拟对象,当调用 recent() 时,它返回“foo”。View 无法遍历字符串,因此会引发异常。下面是两个解决方案,后者允许测试视图是否接收到正确的对象类型。

$mocked->shouldReceive('recent')
    ->once()
    ->andReturn([]);

如果您遇到类似的问题,请检查所有正在测试的代码,并确保您的测试实际上满足所有要求/依赖项......或使用 TDD......我应该从一开始就这样做并避免这个问题.

于 2013-05-18T05:25:02.097 回答