今天要來為大家介紹 Storage Mocking 及 HTTP Mocking!
Storage Mocking 函數
Storage::fake()
:當我們希望在執行測試目標行為時,想驗證 Storage 各類行為是否符合預期,但又不要真的增刪改檔案時,可在測試程式碼中呼叫此函數。UploadedFile::fake()
:這個函數可以模擬出一個已上傳的檔案。Storage::disk($disk)->assertExists()
:可驗證指定的$disk
內,是否有指定檔案存在。需在執行Storage::fake()
後方可使用。Storage::disk(disk)->assertMissing()
:可驗證指定的$disk
內,是否無指定檔案存在。需在執行Storage::fake()
後方可使用。
Storage Mocking 範例:上傳檔案
測試目標:上傳檔案端點- config/filesystems.php
<?php
return [
'default' => env('FILESYSTEM_DISK', 'photos'),
'disks' => [
'photos' => [
'driver' => 'local',
'root' => storage_path('app/photos'),
'throw' => false,
], ],];
- routes/api.php
<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Storage;
Route::post('/photos', function (Request $request) {
$photo = $request->file('photo');
if (empty($photo)) {
return response()->json([], 422);
} Storage::disk('photos')->put('photo.jpg', $photo);
return response()->json('');
})->name('upload.photo');
- 測試程式碼:
<?php以上測試程式碼,測試了 2 種測試案例:
namespace Tests\Feature;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;
class StorageTest extends TestCase{
public function testUploadFileSuccess() {
Storage::fake('photos');
$response = $this->json('POST', route('upload.photo'), [
'photo' => UploadedFile::fake()->image('p.jpg'),
]); Storage::disk('photos')->assertExists('photo.jpg');
} public function testUploadFileFailed() {
Storage::fake('photos');
$response = $this->json('POST', route('upload.photo'), [
'p' => UploadedFile::fake()->image('p.jpg'),
]); Storage::disk('photos')->assertMissing('photo.jpg');
}}
testUploadFileSuccess()
:在這個測試案例函數中,我們驗證了當上傳照片端點被請求,且檔案內容有被放置在指定的欄位時,上傳之檔案將存在於photos
這個 $disk中。testUploadFileFailed()
:在這個測試案例函數中,我們驗證了當上傳照片端點被請求,且檔案內容沒有被放置在指定的欄位時,上傳之檔案將不存在於photos
這個 $disk中。
接著我們來看看 HTTP Mocking 吧!
HTTP Mocking 函數
Http::fake()
:當預進行測試的的測試目標行為,其內部有向外部發送 API 請求,但不希望在執行測試時,真的向外部發送 API 請求時,可在測試程式碼中呼叫此函數。
與其他 fake()
函數不同的是,HTTP Mocking 主要是設定在 Http::fake()
這個函數:
Http::fake([
'<https://weather.tw/taiwan>' => Http::response(
[ 'rain' => 0.8,
'temp_high' => 27,
'temp_low' => 23,
], 200,
[] ),]);
由上面的程式碼可看出,會吃一個陣列,而這個陣列就是預期中要模擬的「呼叫外部API」的行為及其回應。
HTTP Mocking 範例:統整外部天氣資料
測試目標:呼叫氣象局API索取天氣資料並統整
- routes/api.php
<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Route;
Route::get('rain-chance', function (Request $request) {
$response = Http::get('https://weather.tw/taiwan');
// 這邊我們先假設真的有這個網站
// 且其回應值如下:
// {"rain":0.8,"temp_high":27,"temp_low":23}
if ($response->status() !== 200) {
return response()->json(['Error' => 'Failed to get the data of rain chance.']);
} $rainChance = $response->json('rain');
if (!is_float($rainChance)) {
return response()->json(['Error' => 'Failed to get the data of rain chance.']);
} return response()->json(['rain_chance' => $rainChance]);
})->name('get.rain-chance');
- 測試程式碼:
<?php
namespace Tests\Feature;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;
class HttpTest extends TestCase{
public function testGetRainChanceCanWorkWhenGetValidData() {
Http::fake([
'https://weather.tw/taiwan' => Http::response(
[ 'rain' => 0.8,
'temp_high' => 27,
'temp_low' => 23,
], 200,
[] ), ]); $this->get(route('get.rain-chance'))
->assertOk()
->assertJsonStructure(['rain_chance']);
} public function testGetRainChanceCanWorkWhenGetInvalidData() {
Http::fake([
'https://weather.tw/taiwan' => Http::response(
[ 'temp_high' => 27,
'temp_low' => 23,
], 200,
[] ), ]); $this->get(route('get.rain-chance'))
->assertOk()
->assertJson(['Error' => 'Failed to get the data of rain chance.']);
} public function testGetRainChanceCanWorkWhenGet500() {
Http::fake([
'https://weather.tw/taiwan' => Http::response(
'',
500,
[] ), ]); $this->get(route('get.rain-chance'))
->assertOk()
->assertJson(['Error' => 'Failed to get the data of rain chance.']);
}}
以上測試程式碼,測試了 3 種測試案例:
- testGetRainChanceCanWorkWhenGetValidData():在這個測試案例函數中,我們驗證了當降雨機率端點被請求,且外部 API 回應正常時,我們的 API 應當有的正常回應。
- testGetRainChanceCanWorkWhenGetInvalidData():在這個測試案例函數中,我們驗證了當降雨機率端點被請求,且外部 API 回應缺少必要欄位時,我們的 API 應當有的回應(包含錯誤訊息)
- testGetRainChanceCanWorkWhenGet500():在這個測試案例函數中,我們驗證了當降雨機率端點被請求,且外部 API 回應500時,我們的 API 應當有的回應(包含錯誤訊息)。
以上就是今天的介紹囉!
之後讓我們來看看覆蓋率報告以及 phpunit.xml
吧!
如果您喜歡這篇文章,歡迎加入追蹤以接收新文章通知 😄