Издевательский запрос Laravel :: segment method

Это связано с этим вопросом , но после этого решения не удалось решить мою проблему. Я также понимаю, что в собственной документации Laravel говорится, что вы не должны издеваться над объектом Request , но я не уверен, как еще писать этот тест.

Вот видимость кода, который я хочу проверить:

 public function getThirdSegment() { return Request::segment(3); } 

Вот тест, который у меня есть:

 /** * @test */ public function indexReturnsOk() { $this->prepareForTests(); $this->call('GET', '/api/v1/courses'); $this->assertResponseOk(); $this->assertResponseStatus(200); } 

Это не работает, потому что Request::segment(3) возвращает null при запуске PHPUnit. Сначала я попытался высмеять объект Request следующим образом:

 Request::shouldReceive('segment')->andReturn('courses'); 

Но он все равно возвращает null. Затем я попробовал это:

 $request = m::mock('Illuminate\Http\Request'); $request->shouldReceive('segment')->andReturn('courses'); Input::swap($request); 

И метод segment по-прежнему возвращает значение null. Есть ли способ высмеять возвращаемое значение этого метода?

Обновить

Этот код находится в методе регистрации поставщика услуг, но я не думаю, что это является причиной проблемы. Нахождение сайта в браузере делает то, что я ожидаю от него, но запуск PHPUnit, похоже, не соответствует ни маршруту, ни URL-адресу, ни тому, что связано с самим запросом.

Solutions Collecting From Web of "Издевательский запрос Laravel :: segment method"

Лучший ответ здесь пока что я делал это неправильно. Поставщики услуг работают до того, как контроллер еще загружен, а при модульном тестировании Larvel's Illuminate\Foundation\Testing\TestCase загружает приложение (вызывая все службы и службы boot и методы register ) во время выполнения метода setUp , перед тем, как вызовы могут быть оформлены во время выполнения любого отдельного теста.

Я попытался найти решение, переместив логику и получив кое-что, что-то вроде:

 class MyTestClass extends TestCase { public function setUp() { // No call to parent::setUp() // From: Illuminate\Foundation\Testing\TestCase $this->app = $this->createApplication(); $this->client = $this->createClient(); // Not this one! //$this->app->setRequestForConsoleEnvironment(); $this->app->boot(); // ... } public function testWhatever() { // Calls to this will now actually have a request object $this->call('GET', '/api/v1/courses'); } } 

Но это просто не может быть правильным, по крайней мере, это не так.

Вместо этого я полагаю, что лучше всего не полагаться на что-либо в объекте Request изнутри Поставщиков услуг. Вместо этого, почему бы просто не вставить объект, который может делать то, что мне нужно, чтобы сделать это в контроллере, в котором я хочу? Никакой поставщик услуг не нужен, и я могу легко высмеять любой объект, кроме Request в модульных тестах. Я должен был верить документам.

Обновить

Принимая этот ответ на мой собственный вопрос немного дальше, я считаю, что моя первоначальная ошибка заключалась в том, что я использовал объект Request в Провайдере. Я думаю, по ретроспекции, что вы, вероятно, никогда не должны использовать объект Request вообще у поставщика услуг, потому что поставщики загружаются для всего, что связано с laravel (включая команды мастеров, которые, конечно, не должны иметь никакого запроса). Мой исходный код работал в браузере, но я, вероятно, заметил бы проблемы, если бы попытался запустить любые команды artisan.

Я наткнулся на это, пытаясь найти хороший способ обработать композитор представления, который использует этот запрос, и в конечном итоге закончил работу с инсталляцией конструктора – поскольку Laravel использует класс Symfony Request , было очень просто «высмеять» запрос с запросом Request::create('http://myurl.com') и передать его в экземпляр моего класса для тестирования. Гораздо лучше, чем пытаться использовать методы stubbing в классе запросов и не полагается на создание всего приложения Laravel.

Для ясности, композитор представления выглядит в целом следующим образом:

 class SiteLayoutComposer extends BaseComposer { function __construct(Request $request) { $this->request = $request; } public function compose($view) { $templateName = preg_match('/siteurlexample/', $this->request->getHost()) ? 'site1' : 'site2'; $view->with('siteLayout', "layouts.sites.{$templateName}"); } } 

И тест:

 class SiteLayoutComposerTest extends TestCase { public function testWillSetTheSiteLayoutToSite1() { $request = Request::create('http://www.siteurlexample.com'); $view = View::make('home'); $composer = new SiteLayoutComposer($request); $composer->compose($view); $this->assertEquals('layouts.sites.site1', $view->siteLayout); } }