Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel: PHPUnit causing 404s for everything

I'm trying to run some basic unit tests for my Laravel application with PHPUnit.

However, all HTTP requests return a 404 not found HTTP status code, so we are failing at the first hurdle.

After trawling the internet, I have found information about how to remedy this, but so far none of these actually work:

  • Checking I've referenced the named route correctly.
  • Checking that this route has a controller method.
  • Checking that it works in the browser.
  • I've ensured that my application url is set correctly in all the right places: TestCase::$baseUrl, Config->app->url...Its set to http://localhost/myappfolder
  • I've tried different methods from within my unit test methods to get an HTTP response object. So far all result in a 404: $this->route(), $this->action(), $this->call().
  • I've tried removing all references to route protection Middleware from my controllers. I believe that it is disabled when running unit tests, but I've done this as I'm pulling my proverbial hair out trying to diagnose this problem. No effect.
  • My application's roots file has several PHP requires that includes smaller route files. Taylor Otwell has said previously that a routes file like this, but containing require_once can cause these 404 errors. He suggests changing to require. Some developers report that this fixes it for them, but mine have just been require all along. I have also tried moving routes back into the main routes file anyway, but this has not worked either.

Investigations have been usually unusual:

  • If I edit the route() method within Illuminate\Foundation\Testing\Concerns to print out the URL it generates, it is in fact perfectly formed: http://localhost/myprojectfolder/route-url-text. Visiting this page in the browser works fine. Visiting it with cURL works too. Running $this->call() on the URL thats been generated, and then running PHPUnit shows the 404 again. So its just PHPUnit doing something weird.

Here is the code I'm using in the unit test script:

public function testThis()
{
    $response = $this->route('GET', 'myRouteName', [
        'myParam' => 5
    ]);
    dd($response->status()); // 404 - always!
}

Its like there is something stepping in and explicitly throwing a 404...Would really appreciate if someone could shed light on this.

like image 442
kohloth Avatar asked Oct 19 '22 01:10

kohloth


2 Answers

Problem solved. I had this inside app/Providers/AppServiceProvider.php. Something to add to the collective phpunit troubleshooting guide!

public function boot()
{
    URL::forceRootUrl( Config::get('app.url') );
}

I have changed this to:

public function boot()
{
    if (!defined('PHPUNIT_RUNNING')) {
        URL::forceRootUrl( Config::get('app.url') );
    }
}

And put this insite phpunit.xml

<php>
    <const name="PHPUNIT_RUNNING" value="true"/>
</php>
like image 98
kohloth Avatar answered Nov 02 '22 10:11

kohloth


Laravel5.5(vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php)

public function call($method, $uri, $parameters = [], $cookies = [], $files = [], $server = [], $content = null)
{
    $kernel = $this->app->make(HttpKernel::class);
    $files = array_merge($files, $this->extractFilesFromDataArray($parameters));
    $symfonyRequest = SymfonyRequest::create(
        $this->prepareUrlForRequest($uri), $method, $parameters,
        $cookies, $files, array_replace($this->serverVariables, $server), $content
    );
    $response = $kernel->handle(
        $request = Request::createFromBase($symfonyRequest)
    );
    if ($this->followRedirects) {
        $response = $this->followRedirects($response);
    }
    $kernel->terminate($request, $response);

    return $this->createTestResponse($response);
}

It is obvious that the laravel didn't send the request to remote :

$response = $kernel->handle(
    $request = Request::createFromBase($symfonyRequest)
);

You should use co deception.

like image 45
ping ping Avatar answered Nov 02 '22 09:11

ping ping