MrCujo
MrCujo

Reputation: 1333

Laravel: Database tables deleted after running phpunit test

Every time I run a test all my database tables (except for the migrations table) are being deleted and I have to run the migrations again. For instance, if I have the following tables:

migrations
users
tableA
tableB

after running:

phpunit --filter user_can_view_a_record ViewRecordTest tests/Feature/ViewRecordTest.php

my tables are deleted and I end up with just the migrations table.

I'm using MySQL as database and according to the configuration I have set up the tests are being running in memory:

database.php

'connections' => [

        'sqlite' => [
            'driver' => 'sqlite',
            //'database' => env('DB_DATABASE', database_path('database.sqlite')),
            'database' => ':memory:',
            'prefix' => '',
        ],

        'mysql' => [
            'driver' => 'mysql',
            'host' => env('DB_HOST', '127.0.0.1'),
            'port' => env('DB_PORT', '3306'),
            'database' => env('DB_DATABASE', 'forge'),
            'username' => env('DB_USERNAME', 'forge'),
            'password' => env('DB_PASSWORD', ''),
            'unix_socket' => env('DB_SOCKET', ''),
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => '',
            'strict' => false,
            'engine' => null,
            'sticky' => true
        ],
]

phpunit.xml

<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         bootstrap="vendor/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"/>
        <env name="DB_CONNECTION" value="sqlite" />
        <env name="DB_DATABASE" value=":memory:" />
    </php>
</phpunit>

Thanks

Upvotes: 11

Views: 10661

Answers (6)

Joey Rich
Joey Rich

Reputation: 449

I had this problem with all my database tables getting deleted when one test ran, and eventually resolved it by removing the RefreshDatabase trait which was not needed for the test.

use Illuminate\Foundation\Testing\RefreshDatabase; // Remove this
use Tests\TestCase;

class MyTest extends TestCase
{
    use RefreshDatabase; // Remove this
}

Upvotes: 2

Marco Arredondo
Marco Arredondo

Reputation: 79

I had the same issue and this might be helpful for someone. I was working on 2 different Lumen projects both interacting with the same database.

The issue was solved having the same migrations structure on both projects!

The migration files of one project was missing some columns and for some reason had the same behavior of deleting all the database tables after running phpunit.

Upvotes: 0

Onyemenam Ndubuisi
Onyemenam Ndubuisi

Reputation: 123

As mentioned above, this is most likely a problem with Laravel using cached database credentials which point to your local/dev database and not that for your testing.

While running php artisan config:clear solves the problem, there are chances that the problem may occur again in the future.

A permanent solution is to edit your tests\CreatesApplication class like below:

<?php

namespace Tests;

use Illuminate\Contracts\Console\Kernel;
use Illuminate\Support\Facades\Artisan;

trait CreatesApplication
{
    /**
     * Creates the application.
     *
     * @return \Illuminate\Foundation\Application
     */
    public function createApplication()
    {
        $app = require __DIR__.'/../bootstrap/app.php';

        $app->make(Kernel::class)->bootstrap();

        $this->clearCache();

        return $app;
    }

    private function clearCache(): void
    {
        Artisan::call('cache:clear');
    }
}

This ensures that your cache is clear before the tests are run.

Got insights for this response from my experience making tweaks to this response: https://laracasts.com/discuss/channels/laravel/phpunit-is-deleting-my-database?page=1&replyId=700380

Upvotes: 0

Nysso
Nysso

Reputation: 445

the solution of Michael Ameyaw worked well for me in PHPStorm ! thank you.
I wanted to mention that it could be also a cache problem, so try this:

php artisan config:clear

Upvotes: 13

mkojoa
mkojoa

Reputation: 53

I got a solution, if you are using phpStorm look for test framework.

File >> settings >> File & Framework >> Test Framework.

Set a default configuration file to phpunit.xml in your root folder

Upvotes: 1

Igor Skobelev
Igor Skobelev

Reputation: 337

In general you should have separated database with same table structure like staging env. It is normal behavior of unit tests (I mean deleting of tables). Typical flow for testing is (for each test execution):

  1. delete all tables.
  2. Run all migrations (create tables, alter tables, etc).
  3. Load fixtures
  4. Execute tests on fresh database.

Imagine situation, that one of tests change data in for example user table (change email or first name etc) if phpunit don't drop all data next tests will work with incorrect data ( changed by another test). You can check laravel main documentation for more details.

Upvotes: 2

Related Questions