今天要來為大家介紹 Storage Mocking 及 HTTP Mocking!
Storage::fake()
:當我們希望在執行測試目標行為時,想驗證 Storage 各類行為是否符合預期,但又不要真的增刪改檔案時,可在測試程式碼中呼叫此函數。UploadedFile::fake()
:這個函數可以模擬出一個已上傳的檔案。Storage::disk($disk)->assertExists()
:可驗證指定的 $disk
內,是否有指定檔案存在。需在執行 Storage::fake()
後方可使用。Storage::disk(disk)->assertMissing()
:可驗證指定的 $disk
內,是否無指定檔案存在。需在執行 Storage::fake()
後方可使用。測試目標:上傳檔案端點
<?php
return [
'default' => env('FILESYSTEM_DISK', 'photos'),
'disks' => [
'photos' => [
'driver' => 'local',
'root' => storage_path('app/photos'),
'throw' => false,
], ],];
<?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索取天氣資料並統整
<?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 種測試案例:
以上就是今天的介紹囉!
之後讓我們來看看覆蓋率報告以及 phpunit.xml
吧!
如果您喜歡這篇文章,歡迎加入追蹤以接收新文章通知 😄