Laravel 測試教程


參考鏈接:https://laravel-news.com/seeding-data-testing

遷移文件

修改 database/migrations/2014_10_12_000000_create_users_table.php

class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->string('email')->unique();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });

        // following table is storing the relationship between users
        // user_id is following follow_user_id
        Schema::create('following', function (Blueprint $table) {
            $table->integer('user_id')->unsigned()->index();
            $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');

            $table->integer('follow_user_id')->unsigned()->index();
            $table->foreign('follow_user_id')->references('id')->on('users')->onDelete('cascade');

            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('following');
        Schema::dropIfExists('users');
    }
}

執行遷移

php artisan migrate
Migration table created successfully.
Migrated: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_100000_create_password_resets_table

User Model

修改 app/User.php

class User extends Authenticatable
{
    use Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];

    public function follows(User $user)
    {
        $this->following()->attach($user->id);
    }

    public function unfollows(User $user)
    {
        $this->following()->detach($user->id);
    }

    public function following()
    {
        return $this->belongsToMany('App\User', 'following', 'user_id', 'follow_user_id')->withTimestamps();
    }

    public function isFollowing(User $user)
    {
        return !is_null($this->following()->where('follow_user_id', $user->id)->first());
    }
}

這里使用了多對多用戶關系關聯方法[1]

種子文件

創建一個種子文件 database/seeds/UsersTableSeeder.php

php artisan make:seeder UsersTableSeeder

在種子文件中使用工廠方法[2]

use App\User;
use Illuminate\Database\Seeder;

class UsersTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $users = factory(User::class, 10)->create();
    }
}

執行種子文件

  1. 方式一
php artisan db:seed --class=UsersTableSeeder
  1. 方式二

database/seeds/DatabaseSeeder.php 中注冊種子文件

class DatabaseSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $this->call(UsersTableSeeder::class);
    }
}

執行這個 DatabaseSeeder 這個大種子。

php artisan db:seed

測試用例

創建一個測試用例。

php artisan make:test Feature\UserTest

修改 tests/Feature/UserTest.php 的內容。

use App\User;

class UserTest extends TestCase
{
    public function test_have_10_users()
    {
        $this->assertEquals(10, User::count());
    }
}

執行測試

vendor\bin\phpunit

完整的測試文件

<?php

use App\User;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class UserTest extends TestCase
{

    use DatabaseTransactions;

    public function test_follows()
    {
        $userA = User::find(2);
        $userB = User::find(3);

        $userA->follows($userB);

        $this->assertEquals(1, $userA->following()->count());
    }

    public function test_unfollows()
    {
        $userA = User::find(3);
        $userB = User::find(2);

        $userA->unfollows($userB);

        $this->assertEquals(0, $userA->following()->count());
    }

    public function test_A_follows_B_and_C()
    {
        $userA = User::find(1);

        $ids = collect([2, 3, 4, 5, 6, 7, 8, 9, 10]);
        $random_ids = $ids->random(2);

        $userB = User::find($random_ids->pop());
        $userC = User::find($random_ids->pop());

        $userA->follows($userB);
        $userA->follows($userC);

        $this->assertEquals(2, $userA->following()->count());
    }
}

每執行一次測試,都會在數據庫表中插入數據。因此這一次運行結果和前一次可能不一樣

我們不得不像下面這樣,每執行一次測試,就得重新 refresh & seeding嗎?

php artisan migrate:refresh --seed
vendor\bin\phpunit

不用!加上 DatabaseTransactions 就好了。

class UserTest extends TestCase
{
    use DatabaseTransactions;

    ...
}

這個 Trait 將所有測試項放在一個事務中。無論執行結果如何(全部成功或者沒全部成功)都不會對之前的數據庫數據造成任何影響,也就是說這個事務在最后總是回滾

tags: Laravel 項目

  1. belongsToMany 方法用來定義多對多關系。它的第一個參數是關聯表(這里是自關聯,用戶關注用戶);第二個參數是中間表名(這里定義為 following);第三個參數是 $this 指代的 Model 的主鍵在中間表里的字段名;第四個參數是對應表(這里指被關注的人,對應的還是 users 表)的主鍵在中間表里的字段名。 ↩︎

  2. 工廠方法在 database/factories 下定義,可以定義在 ModelFactory.php 中,也可以定義在基於 Model 的工廠方法里(比如 UserFactory.php)。它們都會被 Laravel 處理。 ↩︎


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM