Medium 清新閱讀版
:連結
今天要來為大家介紹 Storage Mocking 及 HTTP Mocking!
Storage::fake()
:當我們希望在執行測試目標行為時,想驗證 Storage 各類行為是否符合預期,但又不要真的增刪改檔案時,可在測試程式碼中呼叫此函數。UploadedFile::fake()
:這個函數可以模擬出一個已上傳的檔案。Storage::disk($disk)->assertExists()
:可驗證指定的 $disk
內,是否有指定檔案存在。需在執行 Storage::fake()
後方可使用。Storage::disk(disk)->assertMissing()
:可驗證指定的 $disk
內,是否無指定檔案存在。需在執行 Storage::fake()
後方可使用。測試目標:上傳檔案端點
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
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');
}
}
以上測試程式碼,測試了 2 種測試案例:
testUploadFileSuccess()
:在這個測試案例函數中,我們驗證了當上傳照片端點被請求,且檔案內容有被放置在指定的欄位時,上傳之檔案將存在於 photos
這個 $disk中。testUploadFileFailed()
:在這個測試案例函數中,我們驗證了當上傳照片端點被請求,且檔案內容沒有被放置在指定的欄位時,上傳之檔案將不存在於 photos
這個 $disk中。接著我們來看看 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」的行為及其回應。
測試目標:呼叫氣象局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 種測試案例:
以上就是今天的介紹囉!
Mocking 的介紹到今天會告一段落,明後天讓我們來看看覆蓋率報告以及 phpunit.xml
吧!