我是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开始)
它引用的行使用'print'构造输出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');
}
}
答案 0 :(得分:1)
它实际上是一个关于在运行测试用例期间如何处理异常的错误,但是这已经修复,只需运行composer update。
答案 1 :(得分:0)
回答我自己的问题 - 错误的原因是代码的某些部分导致PHP错误或异常被抛出。
在这种情况下,问题是从View中抛出异常。 View期望方法recent()返回的值是一个Eloquent Collection(Illuminate \ Database \ Eloquent \ Collection),或者至少是View可以迭代的东西。
HomeControllerTest :: TestIndex方法正在模拟对象,当调用recent()时,它返回'foo'。 View无法迭代字符串,因此会抛出异常。下面是两个解决方案,后者允许测试视图是否接收到正确的对象类型。
$mocked->shouldReceive('recent')
->once()
->andReturn([]);
如果您遇到类似的问题,请检查所有正在测试的代码,并确保您的测试实际上满足所有要求/依赖...或者使用TDD ...我应该从一开始就做的事情和避免了这个问题。