Factory of Relation N:N

Asked

Viewed 78 times

0

I am with an application where users can see or not certain system module according to their permissions. These permissions are saved to the database in a way N:N and managed in UserPolicy, as an example:

Userpolicy.php

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

Userpolicytest.php

public function testCanViewReports()
{
    $user = factory(User::class)->make();
    $user->module()->sync([3]);

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

The test passes, only the data recorded with $user->module()->Sync([3]); are recorded in the database (in the table user_module).

How do I make sure that records are deleted, or don’t need to be created in the database?

  • For me it was not clear, user_module is the link tablet enter the module and the user. Your question is: how to NO use this table and still have the link between user and module? Or got it wrong.

2 answers

2


To perform a rollback of all your test changes, you can use a trait within the test class.

import to Databasetransactions and use within your test as follows.

<?php

namespace Tests\Feature;

use Tests\TestCase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;
use App\User;

// Importe a DatabaseTransactions
use Illuminate\Foundation\Testing\DatabaseTransactions;

class ExampleTest extends TestCase
{
    // Use a trait DatabaseTransactions dessa forma
    use DatabaseTransactions;

    public function testSeuTesteAqui()
    {
        $user = factory(User::class)->create();
        // Aqui o usuário vai ser criado mas quando o teste terminar ele não existirá mais.
    }
}

1

Your question is clear, however, the process of logical construction a little mistaken. Come on...

Laravel offers 2 functions to manage relationships N:N, attach() and sync(). The attach() function records new values in the auxiliary table, while Sync() excludes all and then records new values.

Calling the Sync() function and not wanting the table to be changed is illogical.

If the above answer was helpful to you, all right, if not, continue reading.

Maybe the question you have to ask is:

Why am I worried if records are entered/changed?

So I assume you use the same database for local development and testing, this hinders the development of TDD, resulting in situations like the one you face.

My suggestion:

Create a new database or, what is recommended: install and use the SQL Lite.

In config/database.php, configure a new connection (if you have chosen to use the recommended one, the sqllite connection is already configured).

Open the file phpunit.xml and add the following line to the tag php.

<env name="DB_CONNECTION" value="sqllite" />

Where, value="" receives the connection name.

I hope I helped. D

  • Thank you, very valuable tip to use Sqlite for testing. But I would still like a way to not write the data in the database, as it is done with the user.

  • 1

    In this case, Mysql Transactions may be what you’re looking for. You start the transaction and rollback to not reflect changes in the database. https://laravel.com/docs/5.8/database#database-transactions

Browser other questions tagged

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