Модульное тестирование Laravel 4: заголовки уже отправили ошибку при внедрении макетов с использованием App::instance

Я новичок в 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 с помощью конструкции «print». Что-то вызывает отправку вывода до установки заголовков, но я не могу отследить проблему.

Я могу успешно выполнить все свои тесты, когда контроллер вызывает реальную модель и выполняет вызов базы данных. В то же время я могу успешно издеваться над объектом и выполнять макет без ошибок. Но как только я пытаюсь ввести издевательский объект с помощью 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');
    }

}

person stratton    schedule 17.05.2013    source источник
comment
Несмотря на то, что приведенный ниже ответ решил указанную выше проблему, он вызывает еще один вопрос. Как вы тестируете свой контроллер отдельно от ваших представлений?   -  person stratton    schedule 18.05.2013


Ответы (2)


На самом деле это ошибка обработки исключения во время выполнения тестового примера, однако это было исправлено, просто запустите обновление композитора.

person crynobone    schedule 18.05.2013
comment
Спасибо! PHPUnit теперь выводит исключение, и я действительно могу отследить проблему! На самом деле я запустил обновление композитора, прежде чем задавать вопрос, так что это должно быть действительно свежее исправление. Какая библиотека вызывала эту проблему? - person stratton; 18.05.2013
comment
Этот коммит фактически решает эту проблему github.com/laravel/framework/commit/, там также обсуждение результатов фиксации на github.com/laravel/framework/issues/1332 - person crynobone; 21.05.2013

Отвечая на мой собственный вопрос. Причина ошибки в том, что некоторая часть кода вызывает ошибку PHP или исключение.

В этом случае проблема заключалась в исключении, выброшенном из представления. Представление ожидало, что значение, возвращаемое методом Recent(), было коллекцией Eloquent (Illuminate\Database\Eloquent\Collection) или, по крайней мере, чем-то, что представление могло бы перебрать.

Метод HomeControllerTest::TestIndex издевался над объектом, и при вызове недавнего() он возвращал 'foo'. Представление не может перебирать строку, поэтому оно генерирует исключение. Два решения приведены ниже, последнее позволяет проверить, что представление получило правильный тип объекта.

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

Если у вас возникла аналогичная проблема, изучите весь тестируемый код и убедитесь, что ваши тесты действительно соответствуют всем требованиям/зависимостям... или используйте TDD... что-то, что я должен был сделать с самого начала и избежать этой проблемы. .

person stratton    schedule 18.05.2013