12

In a Laravel/PHPunit test class I added use RefreshDatabase to the class, I understand this should make it so that changes to the database during a test get reverted when the test finishes.

But whenever I run the tests in the class, all tables in the database get dropped, and the tests fail (because the tables don't exist!).

The docs suggest that getting the db to revert after a test is as simple as adding the one line as I did, am I missing something?

4
  • 2
    This is the correct behavior of RefreshDatabase traits. Think about to use a different database for the testing environment. Have a look at this post Commented Jul 10, 2019 at 16:42
  • 5
    I think this is the worst thing the creators of Laravel could make. It is written in every tutorial and none of them says, beware, because you might lose all your data! If you have a working app and need to add tests, this can result in losing your job! Commented May 12, 2024 at 18:47
  • 1
    +1 to what @Dgloria said. I ran into a number of problems because I wasn't aware of this behavior while doing a fresh project with Laravel Breeze. Commented Sep 5, 2024 at 14:47
  • Also the tests have this by default, so the first time you run tests, it wipes all your data. Commented Sep 19, 2024 at 8:19

3 Answers 3

19

If you don't want to wipe and rebuild the database with RefreshDatabase, you can simply use the DatabaseTransactions trait. This will roll back any changes made during testing.

<?php

namespace Tests\Unit;

use Tests\TestCase;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class ExampleTest extends TestCase
{
    use DatabaseTransactions;

    /**
     * A basic test example.
     *
     * @return void
     */
    public function testBasicTest()
    {
        $this->assertTrue(true);
    }
}
Sign up to request clarification or add additional context in comments.

Comments

0

Update your phpunit.xml and add these 2 lines

<server name="DB_CONNECTION" value="sqlite"/>
<server name="DB_DATABASE" value=":memory:"/>

Comments

0

TL;DR you want to use a different database for testing. The right way to do this is to have a .env.testing file that duplicates all your env variables from your existing .env file. Make sure to create a new local database, and then update the DB_DATABASE env var in your new file.

The RefreshDatabase trait is probably the most commonly used trait in testing. It runs migrations before each test run, and it wraps each individual test method in a transaction so that it gets rolled back when the test completes.

When you run a test, Laravel automatically sets the app environment to "testing" (equivalent of app()->environment('testing')), which is why it will look for env vars in the .env.testing file. It's also likely you don't need to copy over all your env vars, but you'll at least need the APP_KEY duplicated to the .env.testing file if you are running Jetstream-provided tests.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.