peffraimidis's avatar

Laravel factory persists in the wrong database

Hello everyone,

I am using a model Employee and we are using multiple databases setup so we also have $connection and $table paremeter set on the model.

We are trying to write tests using factory and we use a .env.testing file to define our connections to our test databases.

The problem is that when we persist a model with factory()->create() the model is persisted is the database that $connection and $table points and not what we have in our .env.testing file.

Any ideas?

0 likes
7 replies
LaryAI's avatar
Level 58

One possible solution to this issue is to override the connection and table settings in the factory definition. You can do this by using the state method in your factory definition.

Here's an example of how you can modify your factory to use the connection and table specified in your .env.testing file:

use App\Models\Employee;
use Illuminate\Database\Eloquent\Factories\Factory;

$factory->define(Employee::class, function (Faker $faker) {
    return [
        'name' => $faker->name,
        // other attributes
    ];
});

$factory->state(Employee::class, 'testing', function (Faker $faker) {
    return [
        'connection' => env('DB_CONNECTION_TESTING'),
        'table' => env('DB_TABLE_TESTING'),
    ];
});

In this example, we define a regular factory for the Employee model. Then, we define a state called 'testing' which overrides the connection and table attributes with the values from your .env.testing file.

To use this state when creating a model instance, you can call the state method on the factory:

$employee = Employee::factory()->state('testing')->create();

This will create an Employee model instance using the connection and table specified in your .env.testing file.

Make sure to replace 'DB_CONNECTION_TESTING' and 'DB_TABLE_TESTING' with the actual environment variable names you have defined in your .env.testing file.

I hope this helps! Let me know if you have any further questions.

1 like
Tray2's avatar

Have you checked your phpunit.xml file, and specified the correct database there?

1 like
Tray2's avatar

@pefremidis For testing you only need one.

<env name="APP_ENV" value="testing"/>
    <env name="BCRYPT_ROUNDS" value="4"/>
    <env name="CACHE_DRIVER" value="array"/>
    <env name="DB_CONNECTION" value="mysql"/>
    <env name="DB_DATABASE" value="mediabase_v2_test"/>
    <env name="MAIL_MAILER" value="array"/>
    <env name="QUEUE_CONNECTION" value="sync"/>
    <env name="SESSION_DRIVER" value="array"/>
    <env name="TELESCOPE_ENABLED" value="false"/>

Update your phpunit.xml to match your settings. This is mine

peffraimidis's avatar

@Tray2 it looks like there is a problem with the RefreshDatabase Trait that I need. The same issue comes with php artisan migrate:fresh.

It looks like it can drop the tables of the default connection but not for all my other connection.

Tray2's avatar

@pefremidis Why are you using more than one database, there is almost never a need for it?

Please or to participate in this conversation.