User mock for testing in Laravel/Phpunit

Asked

Viewed 441 times

0

I have a legacy application in Laravel where users can see or not certain system module according to their permissions. These permissions are saved to the database in N:N form and managed in Userpolicy.

Follow an example:

public function viewReports(User $user)
{
    foreach($user->module as $m){
        if($m->id === 3)
            return true;
    }
}

In order for me to refactor the code, I need to write tests to make sure that the changes don’t break the code. However, I don’t know how to proceed. I momentarily wrote the following test just to make sure it works, but I know it’s not good practice (since I’m using data recorded in the database):

    public function testCanViewReports()
    {
        $user = User::findOrFail(1);

        $this->assertTrue($user->can('viewReports', User::class));
    }

What is the best way to create a stunt double for this test without relying on database?

1 answer

4


The best way is by using Factories and Faker.

You can use the command php artisan make:factory UserFactory.

Factory will be created in the folder "/app/database/Factories/" In this file you can set fake data for the desired model. just return an array with the default Factory data Here you can use Faker to generate dummy data for your Factory

$factory->define(App\User::class, function (Faker $faker) {
    return [
        'name'           => $faker->name,
        'email'          => $faker->unique()->safeEmail,
        'password'       => bcrypt('123456')
    ];
});

Factory documentation https://laravel.com/docs/5.8/database-testing#Factory-States

Documentation of the Faker: https://github.com/fzaninotto/Faker#basic-Usage

In your test method you can use Factory as follows.

$user = factory(App\User::class)->make();

only to have a Model User instance with dummy data, or.

$user = factory(App\User::class)->create();

in this case it creates an instance of the model and also inserts the data into the database.

to overwrite some data you want, just inform inside the create or make method as follows.

$user = factory(App\User::class)->create([
    'name' => 'João'
]);

The right thing is never to test using the production base. Another thing you can add to your test is the "Databasetransactions" trait, which rollbacks all changes made to the database during your test, thus not leaving this data that you generated.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.