Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

rudexpunx's avatar

RefreshDatabase trait doesn't refresh database

From the doc.: ###Resetting The Database After Each Test

It is often useful to reset your database after each test so that data from a previous test does not interfere with subsequent tests. The RefreshDatabase trait takes the most optimal approach to migrating your test database depending on if you are using an in-memory database or a traditional database. Simply use the trait on your test class and everything will be handled for you.

However, it doesn't work for me.

For example, I am creating (only) 3 new posts in an XYth test, however, their IDs are 25, 26, 27.

If I tweak the refreshTestDatabase() method on RefreshDatabase trait by commenting the condition as you can see below, everything works fine and all my tests do pass, even if it takes more time to run the tests...

/**
     * Refresh a conventional test database.
     *
     * @return void
     */
    protected function refreshTestDatabase()
    {
        // if (! RefreshDatabaseState::$migrated) {
            $this->artisan('migrate:fresh');

            $this->app[Kernel::class]->setArtisan(null);

            RefreshDatabaseState::$migrated = true;
        // }

        $this->beginDatabaseTransaction();
    }

Laravel 5.5

0 likes
15 replies
matt_panton's avatar

Have you updated you phpunit.xml file to use a different database for testing. E.g an sqlite database?

rudexpunx's avatar

@matt_panton yes, the database connection (from phpunit.xml) works fine. I am using sql database for testing, and it refreshes it once at the start, but that's about it.

mdecooman's avatar

@rudexpunx

You mean MS SQL Database? Is there a limit on the number of connections?

For my tests I use exclusively in memory DB (whatever the connection) assuming Eloquent will work on any SQL flavor (checking the issues on Github).

<env name="DB_DATABASE" value=":memory:"/>
robrogers3's avatar

i've had this same problem when using DatabaseMigrations.

weirdly upon upgrading to 5.5 the refreshdatabase trait solved it.

drove me crazy. so I called it in some tests explicity.

1 like
robrogers3's avatar

it's a trait. so you can at the beginning of your test do $this->refreshDatabase();

ohffs's avatar

Oddly enough - this has started happening to me today. I've got the RefreshDatabase trait in place - but the tests still seem to leave data kicking around between tests if I use the mysql driver (sqlite in-memory and on-disk are fine). The actual app is fine in use - it just seems to be the tests that are going awry.

If I comment out the lines in the trait as the OP had - the tests run fine. If I call $this->refreshDatabase() in the test it doesn't help - but running Model::truncate() does.

It's really quite annoying as it's making all my CI/Staging tests fail and the code that worked ok is one commit behind a huge monolithic one (yeah, I know - but it was seemingly innocent and just added lots of event() calls and everything was passed using the local sqlite tests).

Is anyone else hitting this just now, or is it just a co-incidence I'm seeing this pop up again? It's been a long Friday, so I've probably just broken something obscure... :-/

ew-stefan's avatar

@ohffs :

Just in case you are using RefreshDatabase (or 'use DatabaseTransactions' for that matter) in the context of Dusk: Dusk makes calls via a browser which happen in a different process and thus cannot be rolled back as part of the testing code and process.

The code of the OP that is commented out basically results in running a migration before each test, which is better accomplished by 'use DatabaseMigrations'.

Please note: https://laravel.com/docs/5.5/dusk#migrations

5 likes
ohffs's avatar

@ew-stefan this is plain old http/unit tests - no dusk. It's quite puzzling - a few other people have mentioned the same thing happening to them. Using DatabaseMigrations works ok - it just seems to be the RefreshDatabase trait that's showing the issue.

afrittella's avatar

Other trick, in your setUp method:

RefreshDatabaseState::$migrated = false;

Of course, refreshing always database means really slow tests...

4 likes
it-is-all-about-laravel's avatar

did you find the solution to this. I'm having the same issue - tests for sqlite in-memory are fine. but running them against mysql i get the issue

2 likes
zanematthew's avatar

I found that just using use DatabaseMigrations; instead of use RefreshDatabase;, works as expected. I haven't looked deeper into this.

5 likes
Bocasz's avatar

for anyone in the future, the most likely issue here is that the connection name for the database used in testing has a "." (dot) in it.

the RefreshDatabase trait calls this function:

 protected function usingInMemoryDatabase()
    {
        $default = config('database.default');

        return config("database.connections.$default.database") === ':memory:';
    }

The config function uses the dot as a separator and treats each segment has an array access so the string:

"database.connections.sqlite.database"

would be the same as:

['database']['connections']['sqlite']['database']

So if you have, lets say 'sqlite.testing' for the connection name its actually checking the array:

['database']['connections']['sqlite']['testing']['database']

Which would return null when checking if database name is ':memory:' making Laravel get confused and not handle your database properly

3 likes
FourthWallCreative's avatar

For anyone else reading this, i've accidentally figured out that using $this->refreshApplication(); in tests that use RefreshDatabase; stores data between tests, causing tests to fail.

1 like

Please or to participate in this conversation.