資料庫測試
簡介
Laravel 提供了數種實用工具與 Assertion (判斷提示) 讓你能更輕鬆地測試由資料庫驅動的網站。此外,通過 Laravel 的 Model Factory 與 Seeder,也能輕鬆地使用專案的 Eloquent Model 與 Eloquent 關聯來測試資料庫。我們會在接下來的說明文件內討論這些強大的工具。
在每個測試後重設資料庫
在進一步繼續之前,我們先來討論如何在每個測試前重設資料庫,這樣一來前一個測試的資料就不會影響到接下來的測試。Laravel 內含了 Illuminate\Foundation\Testing\RefreshDatabase
Trait,會處理這樣的重設。只需要在測試類別內 use 這個 Trait 即可:
1<?php23namespace Tests\Feature;45use Illuminate\Foundation\Testing\RefreshDatabase;6use Illuminate\Foundation\Testing\WithoutMiddleware;7use Tests\TestCase;89class ExampleTest extends TestCase10{11 use RefreshDatabase;1213 /**14 * A basic functional test example.15 *16 * @return void17 */18 public function test_basic_example()19 {20 $response = $this->get('/');2122 // ...23 }24}
1<?php23namespace Tests\Feature;45use Illuminate\Foundation\Testing\RefreshDatabase;6use Illuminate\Foundation\Testing\WithoutMiddleware;7use Tests\TestCase;89class ExampleTest extends TestCase10{11 use RefreshDatabase;1213 /**14 * A basic functional test example.15 *16 * @return void17 */18 public function test_basic_example()19 {20 $response = $this->get('/');2122 // ...23 }24}
定義 Model Factory
概念概覽
首先,來討論有關 Eloquent Model Factory。在測試時,我們可能會需要在執行測試前先插入一些資料到資料庫內。比起在建立這個測試資料時手動指定各個欄位的值,Laravel 中可以使用 Model Factory 來為各個 Eloquent Model 定義一系列的預設屬性。
若要看看如何撰寫 Factory 的範例,請參考專案中的 database/factories/UserFactory.php
。該 Factory 包含在所有的 Laravel 新專案內,裡面有下列 Factory 定義:
1namespace Database\Factories;23use Illuminate\Database\Eloquent\Factories\Factory;4use Illuminate\Support\Str;56class UserFactory extends Factory7{8 /**9 * Define the model's default state.10 *11 * @return array12 */13 public function definition()14 {15 return [16 'name' => $this->faker->name(),17 'email' => $this->faker->unique()->safeEmail(),18 'email_verified_at' => now(),19 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password20 'remember_token' => Str::random(10),21 ];22 }23}
1namespace Database\Factories;23use Illuminate\Database\Eloquent\Factories\Factory;4use Illuminate\Support\Str;56class UserFactory extends Factory7{8 /**9 * Define the model's default state.10 *11 * @return array12 */13 public function definition()14 {15 return [16 'name' => $this->faker->name(),17 'email' => $this->faker->unique()->safeEmail(),18 'email_verified_at' => now(),19 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password20 'remember_token' => Str::random(10),21 ];22 }23}
如上所示,最基礎的 Factory 格式就像這樣,只需繼承 Laravel 的基礎 Factory 類別並定義一個 definition
方法。definition
方法應回傳一組預設的屬性值,會在使用 Factory 建立 Model 時被套用到該 Model 上。
通過 faker
屬性,Factory 就可以存取 Faker PHP 函式庫。該函式庫可用來方便地產生各種類型的隨機資料以進行測試。
可以通過在 config/app.php
設定檔中加上 faker_locale
選項來設定應用程式的 Faker 語系設定。
產生 Factory
若要建立 Factory,請執行 make:factory
Artisan 指令:
1php artisan make:factory PostFactory
1php artisan make:factory PostFactory
新的 Factory 類別會被放在 database/factories
目錄內。
Model 於 Factory 的自動偵測慣例
定義好 Factory 後,就可以使用 Illuminate\Database\Eloquent\Factories\HasFactory
Trait 提供給 Model 的靜態 factory
方法來為該 Model 初始化一個 Factory 實體。
HasFactory
Trait 的 factory
方法會使用慣例來判斷適合用於該 Model 的 Factory。更準確來講,該方法會在 Database\Factories
命名空間下尋找符合該 Model 名稱並以 Factory
結尾的類別。若這些慣例不適合用在你正在寫的專案或 Factory,則可以在 Model 上複寫 newFactory
方法來直接回傳與該 Model 對應的 Factory 實體:
1use Database\Factories\Administration\FlightFactory;23/**4 * Create a new factory instance for the model.5 *6 * @return \Illuminate\Database\Eloquent\Factories\Factory7 */8protected static function newFactory()9{10 return FlightFactory::new();11}
1use Database\Factories\Administration\FlightFactory;23/**4 * Create a new factory instance for the model.5 *6 * @return \Illuminate\Database\Eloquent\Factories\Factory7 */8protected static function newFactory()9{10 return FlightFactory::new();11}
接著,在對應的 Factory 上定義一個 model
屬性:
1use App\Administration\Flight;2use Illuminate\Database\Eloquent\Factories\Factory;34class FlightFactory extends Factory5{6 /**7 * The name of the factory's corresponding model.8 *9 * @var string10 */11 protected $model = Flight::class;12}
1use App\Administration\Flight;2use Illuminate\Database\Eloquent\Factories\Factory;34class FlightFactory extends Factory5{6 /**7 * The name of the factory's corresponding model.8 *9 * @var string10 */11 protected $model = Flight::class;12}
Factory State
State 操作方法可定義一些個別的修改,並可任意組合套用到 Model Factory 上。舉例來說,Database\Factories\UserFactory
Factory 可包含一個 suspended
(已停用) State 方法,用來修改該 Model Factory 的預設屬性值。
State 變換方法通常是呼叫 Laravel 基礎 Factory 類別所提供的 state
方法。這個 state
方法接受一個閉包,該閉包會收到一組陣列,陣列內包含了由這個 Factory 所定義的原始屬性。該閉包應回傳一組陣列,期中包含要修改的屬性:
1/**2 * Indicate that the user is suspended.3 *4 * @return \Illuminate\Database\Eloquent\Factories\Factory5 */6public function suspended()7{8 return $this->state(function (array $attributes) {9 return [10 'account_status' => 'suspended',11 ];12 });13}
1/**2 * Indicate that the user is suspended.3 *4 * @return \Illuminate\Database\Eloquent\Factories\Factory5 */6public function suspended()7{8 return $this->state(function (array $attributes) {9 return [10 'account_status' => 'suspended',11 ];12 });13}
Factory 回呼
Factory 回呼使用 afterMaking
與 afterCreating
方法來註冊,能讓你在產生或建立 Model 時執行額外的任務。要註冊這些回呼,應在 Factory 類別上定義一個 configure
方法。Laravel 會在 Factory 初始化後自動呼叫這個方法:
1namespace Database\Factories;23use App\Models\User;4use Illuminate\Database\Eloquent\Factories\Factory;5use Illuminate\Support\Str;67class UserFactory extends Factory8{9 /**10 * Configure the model factory.11 *12 * @return $this13 */14 public function configure()15 {16 return $this->afterMaking(function (User $user) {17 //18 })->afterCreating(function (User $user) {19 //20 });21 }2223 // ...24}
1namespace Database\Factories;23use App\Models\User;4use Illuminate\Database\Eloquent\Factories\Factory;5use Illuminate\Support\Str;67class UserFactory extends Factory8{9 /**10 * Configure the model factory.11 *12 * @return $this13 */14 public function configure()15 {16 return $this->afterMaking(function (User $user) {17 //18 })->afterCreating(function (User $user) {19 //20 });21 }2223 // ...24}
使用 Factory 來建立 Model
產生 Model
定義好 Factory 後,就可以使用 Illuminate\Database\Eloquent\Factories\HasFactory
trait 提供給 Model 的 factory
靜態方法來產生用於該 Model 的 Factory 實體。來看看一些建立 Model 的範例。首先,我們先使用 make
方法來在不儲存進資料庫的情況下建立 Model:
1use App\Models\User;23public function test_models_can_be_instantiated()4{5 $user = User::factory()->make();67 // Use model in tests...8}
1use App\Models\User;23public function test_models_can_be_instantiated()4{5 $user = User::factory()->make();67 // Use model in tests...8}
可以使用 count
方法來建立包含多個 Model 的 Collection:
1$users = User::factory()->count(3)->make();
1$users = User::factory()->count(3)->make();
套用 State
也可以將 State 套用至 Model 上。若想套用多個 State 變換到 Model 上,只需要直接呼叫 State 變換方法即可:
1$users = User::factory()->count(5)->suspended()->make();
1$users = User::factory()->count(5)->suspended()->make();
複寫屬性
若想複寫 Model 上的一些預設值,可以傳入陣列到 make
方法上。只要指定要取代的屬性即可,剩下的屬性會保持 Factory 所指定的預設值:
1$user = User::factory()->make([2 'name' => 'Abigail Otwell',3]);
1$user = User::factory()->make([2 'name' => 'Abigail Otwell',3]);
或者,也可以直接在 Factory 實體上呼叫 state
方法來內嵌 State 變換:
1$user = User::factory()->state([2 'name' => 'Abigail Otwell',3])->make();
1$user = User::factory()->state([2 'name' => 'Abigail Otwell',3])->make();
大量賦值保護 會在使用 Factory 建立 Model 時自動禁用。
持續性 Model
create
方法會產生 Model 實體並使用 Eloquent 的 save
方法來將其永久保存於資料庫內:
1use App\Models\User;23public function test_models_can_be_persisted()4{5 // 建立單一 App\Models\User 實體...6 $user = User::factory()->create();78 // 建立三個 App\Models\User 實體...9 $users = User::factory()->count(3)->create();1011 // 在測試中使用 Model...12}
1use App\Models\User;23public function test_models_can_be_persisted()4{5 // 建立單一 App\Models\User 實體...6 $user = User::factory()->create();78 // 建立三個 App\Models\User 實體...9 $users = User::factory()->count(3)->create();1011 // 在測試中使用 Model...12}
可以通過將一組屬性陣列傳入 create
方法來複寫該 Factory 的預設 Model 屬性:
1$user = User::factory()->create([2 'name' => 'Abigail',3]);
1$user = User::factory()->create([2 'name' => 'Abigail',3]);
Sequence (序列)
有時候,我們可能會需要為每個建立的 Model 更改某個特定的屬性。可以通過將 State 變換定義為序列來達成。舉例來說,我們可能會想為每個建立的使用者設定 admin
欄位的值為 Y
或 N
:
1use App\Models\User;2use Illuminate\Database\Eloquent\Factories\Sequence;34$users = User::factory()5 ->count(10)6 ->state(new Sequence(7 ['admin' => 'Y'],8 ['admin' => 'N'],9 ))10 ->create();
1use App\Models\User;2use Illuminate\Database\Eloquent\Factories\Sequence;34$users = User::factory()5 ->count(10)6 ->state(new Sequence(7 ['admin' => 'Y'],8 ['admin' => 'N'],9 ))10 ->create();
在上面的範例中,有五個使用者會以 admin
值 Y
建立,另外五個使用者將以 admin
值 N
建立。
若有需要,也可以提供閉包作為序列的值。該閉包會在每次序列需要新值是被叫用:
1$users = User::factory()2 ->count(10)3 ->state(new Sequence(4 fn ($sequence) => ['role' => UserRoles::all()->random()],5 ))6 ->create();
1$users = User::factory()2 ->count(10)3 ->state(new Sequence(4 fn ($sequence) => ['role' => UserRoles::all()->random()],5 ))6 ->create();
在 Sequence 閉包中,可以在注入到閉包中的 Sequence 實體上存取 $index
與 $count
屬性。$index
屬性包含了該 Sequence 到目前為止所進行的迭代數,而 $count
屬性則代表了該 Sequence 總過將被叫用幾次:
1$users = User::factory()2 ->count(10)3 ->sequence(fn ($sequence) => ['name' => 'Name '.$sequence->index])4 ->create();
1$users = User::factory()2 ->count(10)3 ->sequence(fn ($sequence) => ['name' => 'Name '.$sequence->index])4 ->create();
Factory 關聯
Has Many 關聯
接著,來看看如何使用 Laravel 中流利的 Factory 方法建立 Eloquent Model 關聯。首先,假設專案中有個 App\Models\User
Model 以及 App\Models\Post
Model。然後,假設 User
Model 中定義了對 Post
的 hasMany
關聯。我們可以使用 Laravel Factory 提供的 has
方法來建立一個有三篇貼文的使用者。這個 has
方法接受一個 Factory 實體:
1use App\Models\Post;2use App\Models\User;34$user = User::factory()5 ->has(Post::factory()->count(3))6 ->create();
1use App\Models\Post;2use App\Models\User;34$user = User::factory()5 ->has(Post::factory()->count(3))6 ->create();
依照慣例,當傳入 Post
Model 給 has
方法時,Laravel 會假設 User
Model 中有定義這個關聯的 posts
方法。若有需要,可以明顯指定要操作的關聯名稱:
1$user = User::factory()2 ->has(Post::factory()->count(3), 'posts')3 ->create();
1$user = User::factory()2 ->has(Post::factory()->count(3), 'posts')3 ->create();
當然,也可以在關聯 Model 上進行 State 操作。此外,若 State 更改需要存取上層 Model,也可以傳入基於閉包的 State 變換:
1$user = User::factory()2 ->has(3 Post::factory()4 ->count(3)5 ->state(function (array $attributes, User $user) {6 return ['user_type' => $user->type];7 })8 )9 ->create();
1$user = User::factory()2 ->has(3 Post::factory()4 ->count(3)5 ->state(function (array $attributes, User $user) {6 return ['user_type' => $user->type];7 })8 )9 ->create();
使用魔術方法
為了方便起見,可以使用 Laravel 的魔術 Factory 關聯方法來建立關聯。舉例來說,下列範例會使用慣例來判斷應通過 User
Model 上的 posts
關聯方法來建立關聯 Model:
1$user = User::factory()2 ->hasPosts(3)3 ->create();
1$user = User::factory()2 ->hasPosts(3)3 ->create();
在使用魔術方法建立 Factory 關聯時,可以傳入包含屬性的陣列來在關聯 Model 上複寫:
1$user = User::factory()2 ->hasPosts(3, [3 'published' => false,4 ])5 ->create();
1$user = User::factory()2 ->hasPosts(3, [3 'published' => false,4 ])5 ->create();
若 State 更改需要存取上層 Model,可以提供一個基於閉包的 State 變換:
1$user = User::factory()2 ->hasPosts(3, function (array $attributes, User $user) {3 return ['user_type' => $user->type];4 })5 ->create();
1$user = User::factory()2 ->hasPosts(3, function (array $attributes, User $user) {3 return ['user_type' => $user->type];4 })5 ->create();
Belongs To 關聯
我們已經瞭解如何使用 Factory 來建立「Has Many」關聯了,接著來看看這種關聯的想法。使用 for
方法可以用來定義使用 Factory 建立的 Model 所隸屬 (Belong To) 的上層 Model。舉例來說,我們可以建立三個隸屬於單一使用者的 App\Models\Post
Model 實體:
1use App\Models\Post;2use App\Models\User;34$posts = Post::factory()5 ->count(3)6 ->for(User::factory()->state([7 'name' => 'Jessica Archer',8 ]))9 ->create();
1use App\Models\Post;2use App\Models\User;34$posts = Post::factory()5 ->count(3)6 ->for(User::factory()->state([7 'name' => 'Jessica Archer',8 ]))9 ->create();
若已經有應與這些正在建立的 Model 關聯的上層 Model 實體,可以將該 Model 實體傳入 for
方法:
1$user = User::factory()->create();23$posts = Post::factory()4 ->count(3)5 ->for($user)6 ->create();
1$user = User::factory()->create();23$posts = Post::factory()4 ->count(3)5 ->for($user)6 ->create();
使用魔術方法
為了方便起見,可以使用 Laravel 的魔術 Factory 關聯方法來定義「Belongs To」關聯。舉例來說,下列範例會使用慣例來判斷應使用 Post
Model 上的 user
關聯方法來設定這三個貼文應隸屬於哪裡:
1$posts = Post::factory()2 ->count(3)3 ->forUser([4 'name' => 'Jessica Archer',5 ])6 ->create();
1$posts = Post::factory()2 ->count(3)3 ->forUser([4 'name' => 'Jessica Archer',5 ])6 ->create();
Many To Many 關聯
與 Has Many 關聯,「Many to Many」關聯也可以通過 has
方法建立:
1use App\Models\Role;2use App\Models\User;34$user = User::factory()5 ->has(Role::factory()->count(3))6 ->create();
1use App\Models\Role;2use App\Models\User;34$user = User::factory()5 ->has(Role::factory()->count(3))6 ->create();
Pivot 表屬性
若有需要為這些 Model 定義關聯 Pivot/中介資料表上的屬性,則可使用 hasAttached
方法。這個方法接受一個陣列,其中包含 Pivot 資料表上的屬性名稱,第二個引數則為其值:
1use App\Models\Role;2use App\Models\User;34$user = User::factory()5 ->hasAttached(6 Role::factory()->count(3),7 ['active' => true]8 )9 ->create();
1use App\Models\Role;2use App\Models\User;34$user = User::factory()5 ->hasAttached(6 Role::factory()->count(3),7 ['active' => true]8 )9 ->create();
若 State 更改需要存取關聯 Model,可以提供一個基於閉包的 State 變換:
1$user = User::factory()2 ->hasAttached(3 Role::factory()4 ->count(3)5 ->state(function (array $attributes, User $user) {6 return ['name' => $user->name.' Role'];7 }),8 ['active' => true]9 )10 ->create();
1$user = User::factory()2 ->hasAttached(3 Role::factory()4 ->count(3)5 ->state(function (array $attributes, User $user) {6 return ['name' => $user->name.' Role'];7 }),8 ['active' => true]9 )10 ->create();
若已有 Model 實體想讓正在建立的 Model 附加,可以將該 Model 實體傳入 hasAttached
方法。在此範例中,會將三個相同的角色附加給三個使用者:
1$roles = Role::factory()->count(3)->create();23$user = User::factory()4 ->count(3)5 ->hasAttached($roles, ['active' => true])6 ->create();
1$roles = Role::factory()->count(3)->create();23$user = User::factory()4 ->count(3)5 ->hasAttached($roles, ['active' => true])6 ->create();
使用魔術方法
為了方便起見,可以使用 Laravel 的魔術 Factory 關聯方法來定義 Many to Many 關聯。舉例來說,下列範例會使用慣例來判斷應通過 User
Model 上的 roles
關聯方法來建立關聯 Model:
1$user = User::factory()2 ->hasRoles(1, [3 'name' => 'Editor'4 ])5 ->create();
1$user = User::factory()2 ->hasRoles(1, [3 'name' => 'Editor'4 ])5 ->create();
Polymorphic (多型) 關聯
Polymorphic (多型) 關聯 也可以使用 Factory 來建立。Polymorphic 的「Morph Many」關聯使用與一般的「Has Many」關聯相同的方法來建立。舉例來說,若 App\Models\Post
Model 有與 App\Models\Comment
Model 的 morphMany
關聯:
1use App\Models\Post;23$post = Post::factory()->hasComments(3)->create();
1use App\Models\Post;23$post = Post::factory()->hasComments(3)->create();
Morph To 關聯
在建立 morphTo
關聯時無法使用魔法方法。必須直接使用 for
方法,並明顯提供該關聯的名稱。舉例來說,假設 Comment
Model 有個 commantable
方法,該方法定義了 morphTo
關聯。在這種情況下,我們可以直接使用 for
方法來建立三個隸屬於單一貼文的留言:
1$comments = Comment::factory()->count(3)->for(2 Post::factory(), 'commentable'3)->create();
1$comments = Comment::factory()->count(3)->for(2 Post::factory(), 'commentable'3)->create();
Polymorphic (多型) Many to Many 關聯
Polymorphic (多型)「Many to Many」(morphyToMany
/ morphedByMany
) 關聯可以像非 Polymorphic「Many to Many」關聯一樣建立:
1use App\Models\Tag;2use App\Models\Video;34$videos = Video::factory()5 ->hasAttached(6 Tag::factory()->count(3),7 ['public' => true]8 )9 ->create();
1use App\Models\Tag;2use App\Models\Video;34$videos = Video::factory()5 ->hasAttached(6 Tag::factory()->count(3),7 ['public' => true]8 )9 ->create();
當然,也可以使用 has
魔法方法來建立 Polymorphic「Many to Many」關聯:
1$videos = Video::factory()2 ->hasTags(3, ['public' => true])3 ->create();
1$videos = Video::factory()2 ->hasTags(3, ['public' => true])3 ->create();
在 Factory 中定義關聯
若要在 Model Factory 中定義關聯,則通常需要為該關聯的外部索引鍵 (Foreign Key) 指定新的 Factory 實體。一般是使用「相反」的關聯來處理,如 belongsTo
與 morphTo
關聯。舉例來說,若想在建立貼文時建立新使用者,可以像這樣:
1use App\Models\User;23/**4 * Define the model's default state.5 *6 * @return array7 */8public function definition()9{10 return [11 'user_id' => User::factory(),12 'title' => $this->faker->title(),13 'content' => $this->faker->paragraph(),14 ];15}
1use App\Models\User;23/**4 * Define the model's default state.5 *6 * @return array7 */8public function definition()9{10 return [11 'user_id' => User::factory(),12 'title' => $this->faker->title(),13 'content' => $this->faker->paragraph(),14 ];15}
若該關聯的欄位仰賴定義其的 Factory,則可以在屬性中放入閉包。該閉包會收到該 Factory 取值結果的屬性陣列:
1/**2 * Define the model's default state.3 *4 * @return array5 */6public function definition()7{8 return [9 'user_id' => User::factory(),10 'user_type' => function (array $attributes) {11 return User::find($attributes['user_id'])->type;12 },13 'title' => $this->faker->title(),14 'content' => $this->faker->paragraph(),15 ];16}
1/**2 * Define the model's default state.3 *4 * @return array5 */6public function definition()7{8 return [9 'user_id' => User::factory(),10 'user_type' => function (array $attributes) {11 return User::find($attributes['user_id'])->type;12 },13 'title' => $this->faker->title(),14 'content' => $this->faker->paragraph(),15 ];16}
執行 Seeder
若想使用資料庫 Seeder 來在功能測試時修改資料庫,則可以叫用 seed
方法。預設情況下,seed
方法會執行 DatabaseSeeder
,該 Seeder 應用來執行所有其他的 Seeder。或者,也可以傳入指定的 Seeder 類別名稱給 seed
方法:
1<?php23namespace Tests\Feature;45use Database\Seeders\OrderStatusSeeder;6use Database\Seeders\TransactionStatusSeeder;7use Illuminate\Foundation\Testing\RefreshDatabase;8use Illuminate\Foundation\Testing\WithoutMiddleware;9use Tests\TestCase;1011class ExampleTest extends TestCase12{13 use RefreshDatabase;1415 /**16 * Test creating a new order.17 *18 * @return void19 */20 public function test_orders_can_be_created()21 {22 // Run the DatabaseSeeder...23 $this->seed();2425 // Run a specific seeder...26 $this->seed(OrderStatusSeeder::class);2728 // ...2930 // Run an array of specific seeders...31 $this->seed([32 OrderStatusSeeder::class,33 TransactionStatusSeeder::class,34 // ...35 ]);36 }37}
1<?php23namespace Tests\Feature;45use Database\Seeders\OrderStatusSeeder;6use Database\Seeders\TransactionStatusSeeder;7use Illuminate\Foundation\Testing\RefreshDatabase;8use Illuminate\Foundation\Testing\WithoutMiddleware;9use Tests\TestCase;1011class ExampleTest extends TestCase12{13 use RefreshDatabase;1415 /**16 * Test creating a new order.17 *18 * @return void19 */20 public function test_orders_can_be_created()21 {22 // Run the DatabaseSeeder...23 $this->seed();2425 // Run a specific seeder...26 $this->seed(OrderStatusSeeder::class);2728 // ...2930 // Run an array of specific seeders...31 $this->seed([32 OrderStatusSeeder::class,33 TransactionStatusSeeder::class,34 // ...35 ]);36 }37}
或者,也可以使用 RefreshDatabase
Trait 來讓 Laravel 在每次測試前都自動執行資料庫 Seed。可以通過在基礎測試類別上定義 $seed
屬性來完成:
1<?php23namespace Tests;45use Illuminate\Foundation\Testing\TestCase as BaseTestCase;67abstract class TestCase extends BaseTestCase8{9 use CreatesApplication;1011 /**12 * Indicates whether the default seeder should run before each test.13 *14 * @var bool15 */16 protected $seed = true;17}
1<?php23namespace Tests;45use Illuminate\Foundation\Testing\TestCase as BaseTestCase;67abstract class TestCase extends BaseTestCase8{9 use CreatesApplication;1011 /**12 * Indicates whether the default seeder should run before each test.13 *14 * @var bool15 */16 protected $seed = true;17}
當 $seed
屬性為 true
時,各個使用了 RefreshDatabase
Trait 的測試都會在開始前先執行 Database\Seeders\DatabaseSeeder
類別。不過,也可以通過在測試類別內定義 $seeder
屬性來指定要執行的 Seeder。
1use Database\Seeders\OrderStatusSeeder;23/**4 * Run a specific seeder before each test.5 *6 * @var string7 */8protected $seeder = OrderStatusSeeder::class;
1use Database\Seeders\OrderStatusSeeder;23/**4 * Run a specific seeder before each test.5 *6 * @var string7 */8protected $seeder = OrderStatusSeeder::class;
可用的 Assertion
Laravel 為 [PHPUnit] 功能測試提供了多個資料庫 Assertion。我們會在下方討論逐個討論這些 Assertion。
assertDatabaseCount
判斷資料庫中的某個資料表是否包含給定數量的記錄:
1$this->assertDatabaseCount('users', 5);
1$this->assertDatabaseCount('users', 5);
assertDatabaseHas
判斷資料庫中的某個資料表包含符合給定索引鍵/值查詢條件的記錄:
1$this->assertDatabaseHas('users', [3]);
1$this->assertDatabaseHas('users', [3]);
assertDatabaseMissing
判斷資料庫中的某個資料表是否不包含符合給定索引鍵/值查詢條件的記錄:
1$this->assertDatabaseMissing('users', [3]);
1$this->assertDatabaseMissing('users', [3]);
assertDeleted
assertDeleted
判斷給定的 Eloquent Model 是否已從資料庫內刪除:
1use App\Models\User;23$user = User::find(1);45$user->delete();67$this->assertDeleted($user);
1use App\Models\User;23$user = User::find(1);45$user->delete();67$this->assertDeleted($user);
assertSoftDeleted
方法可用來判斷給定 Eloquent Model 是否已「軟刪除 (Soft Delete)」:
1$this->assertSoftDeleted($user);
1$this->assertSoftDeleted($user);
assertModelExists
判斷給定 Model 存在資料庫中:
1use App\Models\User;23$user = User::factory()->create();45$this->assertModelExists($user);
1use App\Models\User;23$user = User::factory()->create();45$this->assertModelExists($user);
assertModelMissing
判斷給定 Model 不存在資料庫中:
1use App\Models\User;23$user = User::factory()->create();45$user->delete();67$this->assertModelMissing($user);
1use App\Models\User;23$user = User::factory()->create();45$user->delete();67$this->assertModelMissing($user);