【问题标题】:Laravel PHPUnit not refreshing after every testLaravel PHPUnit 每次测试后都不刷新
【发布时间】:2018-05-13 05:12:03
【问题描述】:

我目前正在测试登录和注册。问题是每次测试后数据库都不会刷新,因此会导致错误。

我得到的错误:用户 id 应该是 1,但是因为每次测试后数据库没有重置用户 id 是 2。我在我的登录中创建一个新用户并注册测试。

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('/');
    }

}

【问题讨论】:

    标签: php laravel phpunit


    【解决方案1】:

    您必须查看 phpunit.xml 配置文件:如果您使用的是常规测试数据库(不在内存数据库中),它似乎是正确的。

    在 Larav.6 中,refreshTestDatabase() 被调用,在 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();
        }
    

    仅在第一次迭代中,当RefreshDatabaseState::$migratedfalse 时,运行migrate:fresh 并将RefreshDatabaseState::$migrated 设置为true

    在后续迭代中(同一类中的后续测试)会跳过此块。

    【讨论】:

      【解决方案2】:

      您的LoginTest 似乎在RegistrationTest 之前运行。而且由于您在那里创建了一个用户,它会自动获得 id 1。

      RefreshDatabase 不会为每个测试重新迁移,它会在开始之前刷新迁移。

      我建议您从 assertDatabaseHas 中删除 id,因为通过测试 id 并没有真正实现任何目标:

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

      【讨论】:

      • 从文档中它暗示 RefreshDatabase 在每次测试后都会刷新。 ----- “在每次测试后重置数据库通常很有用,这样之前测试的数据不会干扰后续测试。RefreshDatabase 特性采用最优化的方法来迁移测试数据库取决于您使用的是内存数据库还是传统数据库。在您的测试类上使用 trait,一切都会为您处理:"
      • 它在第一次测试之前执行php artisan:fresh,然后将各个测试包装在事务中。如果每次测试都迁移,测试将花费太长时间。您可以通过记录在测试期间运行的查询并亲自查看来进行尝试。事务用于重置数据库,无需迁移。
      • @johnnysoto Here,查看来源。它检查migrated 标志,如果它为假,则运行migrate:fresh 并将标志设置为真。然后它开始一个数据库事务
      猜你喜欢
      • 1970-01-01
      • 2015-11-27
      • 1970-01-01
      • 2014-10-15
      • 1970-01-01
      • 2019-03-09
      • 2018-07-21
      • 2015-10-15
      • 1970-01-01
      相关资源
      最近更新 更多