Laravel phpunit returns 404
Asked Answered
I

10

21

i am new in Laravel. Using local development environment with Homestead Try to run simple test

namespace Tests\Feature;

use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;

class UserTest extends TestCase
{
    /**
     * A basic test example.
     *
     * @return void
     */

    public function testBasicTest()
    {
        $response = $this->get('/');

        $response->assertStatus(200);
    }
}

routes/web.php :

Route::get('/', function () {
    return view('main');
});

Auth::routes();

Route::get('/home', 'HomeController@index')->name('home');

running phpunit returns 404 error

vagrant@homestead:~/code/laravel$ phpunit PHPUnit 6.4.3 by Sebastian Bergmann and contributors.

.F. 3 / 3 (100%)

Time: 1.07 seconds, Memory: 10.00MB

There was 1 failure:

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

/home/vagrant/code/laravel/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestResponse.php:78 /home/vagrant/code/laravel/tests/Feature/UserTest.php:25

I have tried to fix it with these ways

1. Laravel phpunit always 404 updateTestCase.php

    protected $baseUrl = 'http://localhost'

change with

    protected $baseUrl = 'http://laravel.local'

2. https://github.com/dingo/api/issues/540 and next to it https://github.com/dingo/api/issues/571

    use Illuminate\Foundation\Testing\WithoutMiddleware;
    class BankTest extends TestCase {
        use WithoutMiddleware;
  1. Changing APP_URL in .env to

    APP_URL=laravel.local
    

none of this helped

'laravel.local' works fine in browser

Please, help me fix it

Internationale answered 19/11, 2017 at 20:20 Comment(10)
Can you post your routes file?Zimmermann
@FatBoyXPC, added routes to questionHecatomb
Which version of Laravel is this?Zimmermann
@FatBoyXPC, 5.5.19Hecatomb
Have you tried putting http:// in front or the url in APP_URL? I tried to run my tests without http:// and they failed. I don't have $baseUrl in my TestCase at all, just FYI.Zimmermann
@FatBoyXPC, adding 'http://' in APP_URL change error code from 404 to 500:Expected status code 200 but received 500. Failed asserting that false is true.Hecatomb
Looks like you're on to a different error now :) I'd have to see all of the code involved to help you figure that out. This looks like your test is working, though!Zimmermann
Right answer was in /storage/logs/laravel.log, when i run the test, in this log was testing.ERROR that explains what happens. I had to replace '<?=' with '<?echo ' construction in my case.Hecatomb
perfect its working with me @ZimmermannEnunciate
Write the code line $this->withoutExceptionHandling(); as the first line of your test class method testBasicTest(). This will give you more details about the error behind the 404 status.Vargo
H
25

I was running my application with following URL in browser. http://localhost/app/public/

The default unit test having below line was failing. It was getting 404 response instead of 200.

$response = $this->get('/'); $response->assertStatus(200);

I changed APP_URL in .env file as below after reading above comments.

APP_URL=http://localhost

But I was still getting 404 error. After some trial and errors, I found that I needed to clear config cache.

php artisan config:cache

This did the trick and my test started working!!

Hibernate answered 23/3, 2019 at 9:55 Comment(0)
A
11

I had the same problem, and if I run laravel with php artisan serve, it has to be:

APP_URL=http://127.0.0.1:8000/

The APP_URL, has to be exactly the URL of the website.

The website was working, but I didn't have that constant correctly, and PHPUnit was saying all time 404.

Don't forget to clear the cache, after change the config

php artisan config:cache
Acree answered 17/12, 2017 at 14:37 Comment(1)
You may need to run "php artisan config:cache" tooReminisce
F
6

Laravel tests run and expect environment variables. They expect variables like ENV_URL, ENV_KEY,... depending on your test case. It is important that the ENV_URL variable is set to http://localhost disregarding your laravel/server setup. Tests work differently here.

Inside phpunit.xml, the line <server name="APP_ENV" value="testing"/> specifies which testing file to use. value="testing" expects a to use the .env.testing file, if it exists and fallbacks to .env.

There are two approaches that you can do from here on:

Approach A - Using .env.testing:

  1. Create a copy of .env and name it .env.testing.
  2. Verfiy that phpunit.xml includes the .env.testing file, like following <server name="APP_ENV" value="testing"/>
  3. IMPORTANT Edit the .env.testing to use APP_URL=http://localhost as its URL. It doesn't matter under which URL you usually serve your application.
  4. Edit other values to reflect your testing environment
  5. Delete cache using php artisan cache:clear

Approach B - ENV values in phpunit.xml:

You can harcode all ENV values inside the phpunit.xml, like below

   ...
    <php>
        <server name="APP_URL" value="http://localhost"/>
        <server name="APP_KEY" value="base64:e8+BZAzKrSR/LprdHQ2TfMaw+DOTWYmgpkFkEJHV+zw="/>
        <server name="DB_CONNECTION" value="mysql"/>
        <server name="DB_HOST" value="127.0.0.1"/>
        <!-- More ENV values -->
        ...
        <server name="BCRYPT_ROUNDS" value="4"/>
        <server name="CACHE_DRIVER" value="array"/>
        <!-- <server name="DB_CONNECTION" value="sqlite"/> -->
        <!-- <server name="DB_DATABASE" value=":memory:"/> -->
        <server name="MAIL_MAILER" value="array"/>
        <server name="QUEUE_CONNECTION" value="sync"/>
        <server name="SESSION_DRIVER" value="array"/>
        <server name="TELESCOPE_ENABLED" value="false"/>
    </php>
</phpunit>

Bonus - Hybrid Approach:

Use the main .env file and overwrite the APP_URL inside the phpunit.xml. For this, there should not exist an .env.testing file or remove <server name="APP_ENV" value="testing"/> if it does exist.

   ...
    <php>
        <server name="APP_ENV" value="testing"/>

        <!-- IMPORTANT - Overwrite the APP_URL -->
        <server name="APP_URL" value="http://localhost"/> 

        <server name="BCRYPT_ROUNDS" value="4"/>
        <server name="CACHE_DRIVER" value="array"/>
        <!-- <server name="DB_CONNECTION" value="sqlite"/> -->
        <!-- <server name="DB_DATABASE" value=":memory:"/> -->
        <server name="MAIL_MAILER" value="array"/>
        <server name="QUEUE_CONNECTION" value="sync"/>
        <server name="SESSION_DRIVER" value="array"/>
        <server name="TELESCOPE_ENABLED" value="false"/>
    </php>
</phpunit>
Fellows answered 23/12, 2020 at 19:11 Comment(0)
L
5

Have you tried with process isolation set to true in your phpunit.xml file? Our functional tests fail with 404 errors all over the place if we do not have process isolation:

<phpunit backupGlobals="false"
 backupStaticAttributes="false"
 bootstrap="bootstrap/autoload.php"
 colors="true"
 convertErrorsToExceptions="true"
 convertNoticesToExceptions="true"
 convertWarningsToExceptions="true"
 processIsolation="true"
 stopOnFailure="false">
Leatherwood answered 7/5, 2018 at 18:16 Comment(2)
I ran into this same issue and am still struggling to get a full understanding as to why (since I have other very similar tests that work fine). If you want to just run processIsolation on a few tests, you can add this in a docblock comment above the test @runInSeparateProcessComanche
I got OK for the first test and 404 for everything else. After 1 hour of searching, I found you answer and I could fix it. Thanks :)Im
D
5

For anyone having this problem, use APP_URL=http://localhost, this happens if you use vagrant I am not sure for other envs, still investigating.

Developing answered 17/11, 2018 at 19:42 Comment(1)
This works! Not sure why. I created .env.testing and set the APP_URL=http://localhost even .env is APP_URL=http://localhost/app/public.Vellavelleity
R
2

The solution is to simply test using the url returned by

php artisan serve

as base url then run the tests

For example:

    $response = $this->post('http://127.0.0.1:8001/api/register', [
        'email' => '',
        'phone' => '',
        'password' => '',
        'c_password' => '',
        'role_id' => '',
    ]);

    $response->assertStatus(401);
Reliquiae answered 24/3, 2019 at 16:10 Comment(0)
W
1

Leave APP_URL blank in .env file ie

APP_URL=

Weirick answered 20/5, 2022 at 7:7 Comment(0)
K
0

As @TooCooL mentioned, one could set APP_URL=http://localhost even if your project might be something as APP_URL=http://localhost/myproject.
Even better is to create another .env, it shall be called env.testing and there one can change APP_URL or even another database for testing purposes only and so on.
Phpunit will look for configuration at that file .env.testing
Although phpunit works fine even when APP_URL is set on my vhost name on my lamp stack.
Check out your /etc/hosts file as well.

Kristopherkristos answered 1/2, 2019 at 11:56 Comment(0)
A
0

Just for Laravel 8 devs.

Use full url inside get method

 $response = $this->get('http://127.0.0.1:8000');
Apparitor answered 6/1, 2021 at 12:22 Comment(0)
M
0

In relation to whiterook6 answer.

Possible Issue: You are using require_once or include_once to include your routes (bad practice)

Explanation: When processIsolation="false", all test are run by the same process.

In case you have a lot of grouped routes in different files (for example in your web/api.php) using require_once, the routes are only loaded once. If your request is done in your first Test it will likely work, but not in the following Tests.

Running a single test is likely to work in this case:

php artisan test --filter SecondTest

Setting processIsolation="true" will create a new instance of the application in which case the require_once is not an issue.

Fix: Changing this your include to require or include will fix this problem.

Margiemargin answered 17/1 at 10:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.