Medium 清新閱讀版
:連結
指令在現代 Laravel Web Applications 中,也是一個相當常見的應用,而 Laravel 也為此準備許多方便實現測試的函數,以下就來為大家介紹
artisan()
artisan($command, $parameters = [])
$command
的指令,並且帶入參數2 $parameters
所附含的指令參數鍵值對。assertSuccessful()
assertSuccessful()
$this→artisan()
之後,它可以驗證指令是否成功執行完畢,並且回應 exit code 0
(exit code 0
一般代表程式執行完畢且無錯誤或例外發生)。assertFailed()
assertFailed()
$this→artisan()
之後,它可以驗證指令是否非成功執行完畢,只要指令不是回應 exit code 0
,就會被當 Failed
。expectsConfirmation()
expectsConfirmation($question, $answer = 'no')
$this→artisan()
之後,可以驗證是否有預期中的確認訊息輸出。expectsQuestion()
expectsQuestion($question, $answer)
$this→artisan()
之後,可以驗證是否有預期中的詢問訊息輸出。expectsOutput
expectsQuestion($output)
$this→artisan()
之後,可以驗證是否有預期中的文字詢息輸出。介紹完指令相關的測試函數,以下就舉個例子,來為大家展示實務應用吧!
app/Console/Commands/DeleteUser.php
<?php
namespace App\Console\Commands;
use App\Models\User;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;
class DeleteUser extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'delete-user {userId}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Delete the user of given id';
/**
* Execute the console command.
*
* @return int
*/
public function handle(): int
{
$userId = $this->argument('userId');
$user = User::find($userId);
if (empty($user)) {
$this->warn('User not found!');
return 1;
}
if (!$this->confirm('Are you sure to delete this user?')) {
return 1;
}
$logOptions = ['Console output', 'Log file'];
$logType = $this->choice(
'Please select log option:',
$logOptions
);
$user->delete();
$message = 'User deleted';
if ($logType === $logOptions[0]) {
$this->info($message);
} else {
Log::info($message, ['userId' => $userId]);
}
return 0;
}
}
在以上程式碼中,我們實作了一個指令 DeleteUser
,當我們在命令列執行 php artisan delete-user {userId}
時,便會執行這個指令。這個指令有1個數入參數 userId
,其為欲刪除的 User 資料 ID。這個指令的功能與行為大致如下:
userId
嘗試撈取 User 資料,若無資料則顯示錯誤並結束指令,否則繼續流程。Are you sure to delete this user?
文字,讓使用者確認是否繼續執行刪除指令,並依使用者之回應決定提前結束指令或繼續流程。0
tests/Feature/CommandTest.php
<?php
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class CommandTest extends TestCase
{
use RefreshDatabase;
public function testUserNotFound()
{
$this->artisan('delete-user',['userId' => 1])
->expectsOutput('User not found!')
->assertFailed();
}
public function testSuccessDeleteUser()
{
$user = User::factory()->create();
$userId = $user->id;
$this->artisan('delete-user', ['userId' => $userId])
->expectsConfirmation(
'Are you sure to delete this user?', 'yes'
)
->expectsQuestion('Please select log option:', 0)
->expectsOutput('User deleted')
->assertSuccessful();
$this->assertDatabaseCount('users', 0);
}
public function testCancelDeleteUser()
{
$user = User::factory()->create();
$userId = $user->id;
$this->artisan('delete-user', ['userId' => $userId])
->expectsConfirmation('Are you sure to delete this user?')
->assertSuccessful();
$this->assertDatabaseHas('users', [
'id' => $userId,
]);
}
}
以上測試程式碼,共分為3個測試案例情境:
testUserNotFound()
,測試的是當給定的 userId
,無法在資料庫找到對應資料時,指令應有的對應行為與輸出testSuccessDeleteUser()
,測試的是當給定的 userId
,可在資料庫找到對應資料,且使用者於確認提示時輸入 yes
後,指令應有的對應行為與輸出。testCancelDeleteUser()
,測試的是當給定的 userId
,可在資料庫找到對應資料,且使用者於確認提示時輸入 no
後,指令應有的對應行為與輸出。以上就是針對指令測試的介紹,希望對各讀者有所幫助。
明天來介紹測試「失敗」吧!