iT邦幫忙

2022 iThome 鐵人賽

DAY 21
0
DevOps

自動化測試大作戰系列 第 21

Mocking(六):Storage & HTTP

  • 分享至 

  • xImage
  •  

Medium 清新閱讀版連結

今天要來為大家介紹 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
    
    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 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 應當有的回應(包含錯誤訊息)。

以上就是今天的介紹囉!

Mocking 的介紹到今天會告一段落,明後天讓我們來看看覆蓋率報告以及 phpunit.xml 吧!

參考資料


上一篇
Mocking(五):Queue
下一篇
phpunit.xml
系列文
自動化測試大作戰31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言