0

I am currently testing the login and register. The problem is that the database is not refreshing after every test so it's causing an error.

Error that I am getting: The user id should be 1, but because the database is not resetting after every test the user id is 2. I create a new user in my login and register test.

1) Tests\Unit\RegisterTest::successful
Failed asserting that a row in the table [users] matches the attributes {
    "id": 1,
    "username": "JohnRock",
    "email": "hello@email.com"
}.

Found: [
    {
        "id": 2,
        "username": "JohnRock",
        "email": "hello@email.com",
        "password": "$#^TTUG#$ORY#$&*RY#$YRY#$:RY:#$YRU$#YRP",
        "remember_token": null,
        "created_at": "2018-05-13 03:41:35",
        "updated_at": "2018-05-13 03:41:35"
    }
].
<?php

namespace Tests\Unit;

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

class RegisterTest extends TestCase
{

    use RefreshDatabase;

    /**
     * A basic test example.
     *
     * @return void
     */


    /** @test */
    public function successful_register()
    {
        $username  = 'JohnRock';
        $email     = 'hello@email.com';
        $password  = 'fjIRHJV@#(*UH(@#*H78))';

        $user = [
            'username'              => $username,
            'email'                 => $email,
            'password'              => $password,
            'password_confirmation' => $password
        ];

        $response = $this->post('/register', $user);

        $this->assertDatabaseHas('users', [
            'id'       => 1,
            'username' => $username,
            'email'    => $email
        ]);
    }

}
<?php

namespace Tests\Unit;

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

class LoginTest extends TestCase
{

    use RefreshDatabase;

    /**
     * A basic test example.
     *
     * @return void
     */


    /** @test */
    public function login_successful()
    {
        $user = factory('App\User')->create();

        $response = $this->post('/login', [
            'username' => $user->username,
            'password' => $user->password
        ]);

        $response->assertRedirect('/');
    }

}
johnnysoto
  • 1
  • 1
  • 3

2 Answers2

1

You have to see phpunit.xml config file: if you are using conventional Test Database (not in memory database) it seems correct.

In Larav.6 the refreshTestDatabase() is called, defined in Illuminate\Foundation\Testing\RefreshDatabase trait.

    /**
     * Refresh a conventional test database.
     *
     * @return void
     */
    protected function refreshTestDatabase()
    {
        if (! RefreshDatabaseState::$migrated) {
            $this->artisan('migrate:fresh', [
                '--drop-views' => $this->shouldDropViews(),
                '--drop-types' => $this->shouldDropTypes(),
            ]);

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

            RefreshDatabaseState::$migrated = true;
        }

        $this->beginDatabaseTransaction();
    }

Only on First iteration, when RefreshDatabaseState::$migrated is false, migrate:fresh is runned and RefreshDatabaseState::$migrated setted to true.

On the subsequent iterations (subsequent tests in the same class) this block is skipped.

Alessandro
  • 409
  • 5
  • 12
0

Your LoginTest seems to be running before the RegistrationTest. And since you create a user there, it automatically gets id 1.

The RefreshDatabase doesn't remigrate for every test, it refreshes migrations before starting.

I recommend you remove the id from assertDatabaseHas, since don't really achieve anything by testing for id:

$this->assertDatabaseHas('users', [
    'username' => $username,
    'email'    => $email,
]);
DevK
  • 9,597
  • 2
  • 26
  • 48
  • 2
    From the docs it implies that RefreshDatabase does refresh after every 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. Use the trait on your test class and everything will be handled for you:" – johnnysoto May 13 '18 at 05:42
  • 1
    It performs `php artisan:fresh` before the first test and then wraps individual tests in transactions. The tests would take far too long if it migrated for every test. You can try it by logging the queries that run during the tests and see for yourself. The transactions are for resetting the database, no need for migrations to do that. – DevK May 13 '18 at 05:45
  • @johnnysoto [Here](https://github.com/laravel/framework/blob/5.6/src/Illuminate/Foundation/Testing/RefreshDatabase.php#L50), check the source. It checks for `migrated` flag, if it's false it runs `migrate:fresh` and sets the flag to true. Then it begins a database transaction – DevK May 13 '18 at 05:51