lundi 16 septembre 2019

Laravel API Testing - http request different baseUrl and pathInfo between browser and PHPUnit

I am writing Unit Tests in PHPUnit to test my Laravel API. I have stripped things right down to the basics to isolate my current problem. In my .env file I have included an env variable to allow me to verify the .env file I want to use is in use:

.env: CHECK_AM_USING_RIGHT_ENV="Oh yeah"

In routes/web.php I have (I know I should be using route/api.php and the api prefix, but web.php should still work, I don't think api.php vs web.php is the cause of my issue):

Route::get('/hi',function() {
    return json_encode(['Helo','world',env('CHECK_AM_USING_RIGHT_ENV','none')]);
})->name('hi');

This means I have no authentication requirements (no controller with auth midleware).

My web app is in a dashboard folder on my loacal apache, hence .env has APP_URL="https://ift.tt/29cboqf", so route('hi') returns http://127.0.0.1/dashboard/hi

When I hit http://127.0.0.1/dashboard/hi in chrome, I get what I would expect:

[
  "Helo",
  "world",
  "Oh yeah"
]

I have created a PHPUnit Test to test this api endpoint:

tests/feature/TrivialTest.php

<?php

namespace Tests\Feature;

use Tests\TestCase;

class TrivialTest extends TestCase
{
    public function testTrivial1()
    {
        $uri = route('hi');
        dump($uri);// included to verify the address of the end point we are hitting
        $response = $this->get($uri);
        $response->assertStatus(200);
        $response->dump();
    }
}

But this test always fails with 404 returned not 200:

PHPUnit 5.7.21 by Sebastian Bergmann and contributors.

."http://127.0.0.1/dashboard/hi"
"Oh yeah"
F.                                                                 3 / 3 (100%)

Time: 760 ms, Memory: 14.00MB

There was 1 failure:

1) Tests\Feature\TrivialTest::testTrivial1
Expected status code 200 but received 404.
Failed asserting that false is true.

But the output confirms we are asking for the right endpoint, and using the right .env file.

To diagnose this, I included a dd($request); in the match(Request $request) [] method in the vendor\laravel\framework\src\Illuminate\Routing\RouteCollection.php to allow me to compare what was different about the two requests:

Request when hitting with Chrome Browser (differences only):

  pathInfo: "/hi"
  requestUri: "/dashboard/hi"
  baseUrl: "/dashboard"
  basePath: "/dashboard"

  #headers: array:12 [▼
      "host" => array:1 [0 => "localhost"]
      "connection" => array:1 [0 => "keep-alive"]
      "cache-control" => array:1 [ 0 => "max-age=0"]
      "upgrade-insecure-requests" => array:1 [0 => "1"]
      "user-agent" => array:1 [0 => "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.75 Safari/537.36"]
      "sec-fetch-mode" => array:1 [0 => "navigate"]
      "sec-fetch-user" => array:1 [0 => "?1"]
      "accept" => array:1 [0 => "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3"]
      "sec-fetch-site" => array:1 [0 => "none"]
      "accept-encoding" => array:1 [0 => "gzip, deflate, br"]
      "accept-language" => array:1 [0 => "en,en-AU;q=0.9"]
      "cookie" => array:1 [0 => "XSRF-TOKEN=eyJpdiI6InlHT2FVNUNxaFVCb09TSzRxTDhpUFE9PSIsInZhbHVlIjoiSGxCMTlqQUtTVmthV3AyOVRueFJvNmxxNU5xR0M4bkt3b3ZaVWdnaXpzSlJSdXNnNkJTYXBsM2s1ekdvd3lCMXBGak..."]
    ]

PHPUnit Test Request when executing test:

  pathInfo: "/dashboard/hi"
  requestUri: "/dashboard/hi"
  baseUrl: ""
  basePath: "" 

  #headers: array:5 [
      "host" => array:1 [ 0 => "127.0.0.1"]
      "user-agent" => array:1 [ 0 => "Symfony/3.X"]
      "accept" => array:1 [ 0 => "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"]
      "accept-language" => array:1 [ 0 => "en-us,en;q=0.5"]
      "accept-charset" => array:1 [ 0 => "ISO-8859-1,utf-8;q=0.7,*;q=0.7"]
  ]

The documentation says the csrf middleware is turned off for the PHPUnit testing, (and if that was the problem you don't get a 404 not found error).

My phpunit.xml is out-f-the-box:

<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         bootstrap="bootstrap/autoload.php"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false">
    <testsuites>
        <testsuite name="Feature">
            <directory suffix="Test.php">./tests/Feature</directory>
        </testsuite>

        <testsuite name="Unit">
            <directory suffix="Test.php">./tests/Unit</directory>
        </testsuite>
    </testsuites>
    <filter>
        <whitelist processUncoveredFilesFromWhitelist="true">
            <directory suffix=".php">./app</directory>
        </whitelist>
    </filter>
    <php>
        <env name="APP_ENV" value="testing"/>
        <env name="CACHE_DRIVER" value="array"/>
        <env name="SESSION_DRIVER" value="array"/>
        <env name="QUEUE_DRIVER" value="sync"/>
    </php>
</phpunit>

I have tried changing as that matches the APP_ENV in my .env, but that has no noticable effect.

Why are the pathInfo and RequestUri values different in the request from PHPUnit and Chrome? Is that what is causing the problem?

Do I need to add headers? If so, what headers and why do missing headers cause a 404?

Thanks in advance



via Chebli Mohamed

Aucun commentaire:

Enregistrer un commentaire