在 Laravel 中為 REST API 實(shí)施功能測(cè)試

yanding 2023-06-12 353

介紹

使用測(cè)試用例會(huì)讓您感到害怕嗎?您是否正在尋找一個(gè)簡(jiǎn)單的教程來開始在 Laravel 中進(jìn)行功能測(cè)試?然后,我們堅(jiān)持讓您堅(jiān)持這個(gè)循序漸進(jìn)的指南,以消除您的疑慮并學(xué)習(xí)在 Laravel 應(yīng)用程序中進(jìn)行測(cè)試。

Laravel 中的功能測(cè)試:什么、為什么以及如何?

Laravel 中的功能測(cè)試是什么?

在開發(fā)應(yīng)用程序時(shí),您往往會(huì)擔(dān)心在執(zhí)行功能或模塊時(shí)代碼會(huì)被破壞。為了避免出現(xiàn)這種情況,在您的應(yīng)用程序中實(shí)施測(cè)試很重要。

特性測(cè)試是最常用和最重要的測(cè)試類型之一。它允許您測(cè)試應(yīng)用程序代碼的主要部分,這些代碼具有相互交互的對(duì)象、HTTP 請(qǐng)求、JSON 等。

為什么在 Laravel 中進(jìn)行功能測(cè)試?

  • 使工作順暢

  • 避免破壞整個(gè)應(yīng)用程序

  • 代碼可維護(hù)性

  • 應(yīng)用穩(wěn)定性

  • 應(yīng)用程序崩潰時(shí)輕松調(diào)試

  • 輕松確定應(yīng)用程序崩潰背后的原因

最好的部分是測(cè)試是自動(dòng)化的。它會(huì)發(fā)現(xiàn)代碼中的漏洞并允許您正確開發(fā)功能。

Laravel 中的特性測(cè)試是如何工作的?

Laravel 支持 PHPUnit 測(cè)試。您的 Web 應(yīng)用程序附帶一個(gè) phpunit.xml 文件,其中包含測(cè)試 Laravel 應(yīng)用程序所需的所有設(shè)置。您的 phpunit.xml 文件設(shè)置了用于測(cè)試的 laravel 環(huán)境。因此無需創(chuàng)建新的 XML 文件!

下面是 Laravel 8 框架附帶的示例 phpunit.xml 文件。

<?xml version="1.0" encoding="UTF-8"?><phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
        bootstrap="供應(yīng)商/autoload.php"
        顏色=“真”>
   <測(cè)試套件>
       <測(cè)試套件名稱="單元">
           <目錄后綴="Test.php">./tests/Unit</directory>
       </測(cè)試套件>
       <測(cè)試套件名稱="功能">
           <目錄后綴="Test.php">./tests/Feature</directory>
       </測(cè)試套件>
   </測(cè)試套件>
   <覆蓋過程UncoveredFiles="true">
       <包括>
           <目錄后綴=".php">./app</directory>
       </include>
   </覆蓋>
   <php>
       <server name="APP_ENV" value="testing"/>
       <服務(wù)器名稱="BCRYPT_ROUNDS" 值="4"/>
       <server name="CACHE_DRIVER" value="array"/>
       <server name="MAIL_MAILER" value="array"/>
       <server name="QUEUE_CONNECTION" value="sync"/>
       <server name="SESSION_DRIVER" value="array"/>
       <server name="TELESCOPE_ENABLED" value="false"/>
   </php></phpunit>

初始設(shè)置

對(duì)于本教程,我們將使用酒店評(píng)論 api。終端用戶可以對(duì)酒店進(jìn)行點(diǎn)評(píng),可以對(duì)酒店點(diǎn)評(píng)進(jìn)行添加、更新、刪除以及酒店點(diǎn)評(píng)列表操作。

通過以下命令創(chuàng)建 laravel 應(yīng)用程序

作曲家創(chuàng)建項(xiàng)目 --prefer-dist laravel/laravel hotel_review_api_testcd hotel_review_api_test

打開 .env 文件并更新數(shù)據(jù)庫詳細(xì)信息。

DB_CONNECTION=mysqlDB_HOST=127.0.0.1DB_PORT=3306DB_DATABASE=hotel_test_apiDB_USERNAME=root數(shù)據(jù)庫密碼=

創(chuàng)建模型和遷移

對(duì)于模型,運(yùn)行以下命令。

php artisan make:model 酒店php artisan make:model 評(píng)論

對(duì)于遷移,請(qǐng)運(yùn)行以下命令。

php artisan make:migration create_hotel_table	php artisan make: 遷移 create_review_table

發(fā)展。維持。優(yōu)化。部署 - 與 Bacancy!
您是否正在尋找熟練的開發(fā)人員來構(gòu)建高度優(yōu)化的應(yīng)用程序?與我們聯(lián)系以聘請(qǐng) Laravel 開發(fā)人員。聯(lián)系最好的,得到最好的!時(shí)期!

創(chuàng)建數(shù)據(jù)庫表

現(xiàn)在通過下面提到的代碼更新遷移文件。

我們將更新用戶表、酒店表和評(píng)論表文件。按照指示添加列。您可以根據(jù)需要編輯列。

用戶表

公共功能向上(){
 Schema::create('users', function (Blueprint $table) {
     $table->bigIncrements('id')->unsinged();
     $table->string('名字');
     $table->string('email')->unique();
     $表->時(shí)間戳();
  });
}

酒店餐桌

公共功能向上(){
 Schema::create('hotels', function (Blueprint $table) {
    $table->bigIncrements('id')->unsinged();
    $table->string('名字', 100);
    $table->text('地址')->nullable();
    $table->float('star')->nullable();
   $table->tinyInteger('active')->default(1)->comment = '1 = active,0 = Inactive';
    $表->時(shí)間戳();
    $表->softDeletes();
 });}

審查表

公共功能向上(){
  Schema::create('reviews', function (Blueprint $table) {
     $table->bigIncrements('id')->unsinged();
     $table->string('標(biāo)題', 100);
     $table->text('描述', 100);
     $table->unsignedBigInteger('user_id')->nullable();
     $table->unsignedBigInteger('hotel_id')->nullable();
     $表->時(shí)間戳();$表->softDeletes(); $table->foreign('user_id')->references('id')->on('users')->onDelete('CASCADE')->onUpdate('CASCADE'); $table->foreign('hotel_id')->references('id')->on('hotels')->onDelete('CASCADE')->onUpdate('CASCADE');
  });
}

運(yùn)行遷移

php 工匠遷移

生成 API 路由和 CRUD 業(yè)務(wù)邏輯

打開 \routes\api.php 并使用以下代碼片段為我們的 API 生成路由。我們將有五個(gè) API。

路線\ api.php

// 獲取所有活躍的酒店數(shù)據(jù)Route::get('酒店', [HotelController::class,'getAllHotelData']);
// 獲取特定酒店數(shù)據(jù)Route::get('hotel/{hotel_id}', [HotelController::class,'getHotelDataById']);
// 添加新的酒店評(píng)論Route::post('save-hotel-review', [HotelController::class,'storeHotelReviewData']);
// 更新酒店評(píng)論Route::put('update-hotel-review/{review_id}', [HotelController::class,'updateHotelReviewData']);
// 刪除酒店評(píng)論Route::delete('review/{review_id}', [HotelController::class,'deleteHotelReview']);

增刪改查業(yè)務(wù)邏輯

對(duì)于CRUD操作的業(yè)務(wù)邏輯,新建一個(gè)HotelController.php文件。我們不會(huì)指定 API 的代碼片段。但是如果您想看一下,這里是指向HotelController.php的 Github 鏈接。我們將遵循這五個(gè) API。

  • /api/hotels: 返回所有酒店數(shù)據(jù)

  • /api/hotel/{hotel_id}:返回特定酒店的數(shù)據(jù)

  • /api/save-hotel-review: 添加酒店評(píng)論

  • /api/update-hotel-review/{review_id}:更新酒店評(píng)論

  • /api/review/{review_id}: 刪除酒店評(píng)論

在 Laravel 應(yīng)用程序中創(chuàng)建功能測(cè)試

本節(jié)將為我們的應(yīng)用程序創(chuàng)建我們的第一個(gè)功能測(cè)試。運(yùn)行以下命令以生成一個(gè)名為 HotelTest 的用于測(cè)試的文件。

php artisan make:test HotelTest

該命令將使用以下代碼在測(cè)試 > 功能文件夾中創(chuàng)建一個(gè)名為 HotelTest.php 的新文件。

斷言真(真);
   }}

更新 HotelTest.php

我們將為應(yīng)用程序的每個(gè)單元編寫測(cè)試。我們進(jìn)行了書面測(cè)試以確保:可以添加、刪除、更新和列出有效的酒店評(píng)論。使用以下代碼更新HotelTest.php 。

<?php
命名空間測(cè)試\功能;
使用測(cè)試\測(cè)試用例;使用 App\Models\Hotel;使用 App\Models\User;使用 App\Models\Review;使用碳\碳;

獲取特定酒店的活躍酒店數(shù)據(jù)

類 HotelTest 擴(kuò)展了 TestCase{
   /**
    * 基于酒店ID獲取活躍酒店數(shù)據(jù)的功能測(cè)試
    *
    * @return 無效
    */
   公共功能 test_get_active_hotel_by_id()
   {
       $hotel_id = Hotel::where('active', 1)->get()->random()->id;
       $response = $this->get('/api/hotel/' . $hotel_id)
           ->assertStatus(200)
           ->assertJsonStructure(
               [
                   '代碼',
                   '信息',
                   '數(shù)據(jù)'=> [
                       'ID',
                       '姓名',
                       '星星',
                       '評(píng)論'=> [
                           '*' => [
                               “ID”,
                               “標(biāo)題”,
                               “描述”,
                               “作者”,
                               “創(chuàng)建”,
                               “更新時(shí)間”
                           ],
                       ]
                   ],
               ]
           );
   }

獲取所有活躍的酒店數(shù)據(jù)

    /**
    * 獲取所有活躍酒店數(shù)據(jù)的功能測(cè)試
    *
    * @return 無效
    */
   公共功能 test_get_all_active_hotels()
   {
       $response = $this->get('/api/hotels')
           ->assertStatus(200)
           ->assertJsonStructure(
               [
                   '代碼',
                   '信息',
                   '數(shù)據(jù)'=> [
                       '*' => [
                           “ID”,
                           “姓名”,
                           “地址”,
                           “星星”,
                           “創(chuàng)建”,
                           “更新時(shí)間”,
                           “積極的”,
                           “評(píng)論”=> [
                               '*' => [
                                   “ID”,
                                   “標(biāo)題”,
                                   “描述”,
                                   “作者”,
                                   “創(chuàng)建”,
                                   “更新時(shí)間”
                               ],
                           ],
                       ],
                   ],
               ]
           );
   }

獲取特定酒店的所有非活動(dòng)酒店數(shù)據(jù)

   /**
    * 基于酒店ID獲取非活躍酒店數(shù)據(jù)的功能測(cè)試
    *
    * @return 無效
    */
   公共功能 test_for_get_inactive_hotel_by_id()
   {
       $hotel_id = Hotel::where('active', 0)->get()->random()->id;
       $response = $this->get('/api/hotel/' . $hotel_id)
           ->assertStatus(200)
           ->assertJsonStructure(
               [
                   '代碼',
                   '信息',
               ]
           );
   }

添加新評(píng)論

    /**
    * 添加新評(píng)論的功能測(cè)試
    *
    * @return 無效
    */
   公共功能 test_for_add_hotel_review()
   {
       $user = 用戶::創(chuàng)建([
           '名稱' => 蘭德(),
           '電子郵件' => 蘭德()。' .abc@xyz.com ',
           'created_at' => Carbon::now(),
           'updated_at' => Carbon::now(),
       ]);
       //$user = User::create($userData);
       $酒店=酒店::創(chuàng)建([
           '名稱' => 蘭德(),
           '明星'=> 2,
           'address' => '市政廳對(duì)面,Nr。Sakar II & IV, Ashram Rd, Ellisbridge, Ahmedabad, Gujarat 380006',
           '活動(dòng)'=> 0,
           'created_at' => Carbon::now(),
           'updated_at' => Carbon::now(),
       ]);

       $有效載荷= [
           "hotel_id" => $hotel->id,
           "user_id" => $user->id,
           "review_title" => "測(cè)試",
           “review_data”=>“測(cè)試說明”
       ];

       $this->json('POST', 'api/save-hotel-review', $payload)
           ->assertStatus(200)
           ->assertJson([
               '代碼'=>'200',
               'message' => '酒店評(píng)論已保存。',
           ]);
   }

更新具體評(píng)論

    /**
    * 基于評(píng)論 ID 更新評(píng)論的功能測(cè)試
    *
    * @return 無效
    */
   公共功能 test_for_update_hotel_review()
   {
       $user = 用戶::創(chuàng)建([
           '名稱' => 蘭德(),
           '電子郵件' => 蘭德()。' .abc@xyz.com ',
           'created_at' => Carbon::now(),
           'updated_at' => Carbon::now(),
       ]);
       //$user = User::create($userData);
       $酒店=酒店::創(chuàng)建([
           '名稱' => 蘭德(),
           '明星'=> 2,
           'address' => '市政廳對(duì)面,Nr。Sakar II & IV, Ashram Rd, Ellisbridge, Ahmedabad, Gujarat 380006',
           '活動(dòng)'=> 0,
           'created_at' => Carbon::now(),
           'updated_at' => Carbon::now(),
       ]);

       $hotelReview = 評(píng)論::創(chuàng)建([
           'title' => '好萊塢好酒店',
           'description' => 'HollywoodInn 是一家非常不錯(cuò)的酒店。',
           'user_id' => $user->id,
           'hotel_id' => $hotel->id,
           'created_at' => Carbon::now(),
           'updated_at' => Carbon::now(),
       ]);

       $有效載荷= [
           "hotel_id" => $hotel->id,
           "user_id" => $user->id,
           "review_title" => "測(cè)試",
           “review_data”=>“測(cè)試說明”
       ];

       $this->json('PUT', 'api/update-hotel-review/' . $hotelReview->id, $payload)
           ->assertStatus(200)
           ->assertJson([
               '代碼'=>'200',
               'message' => '酒店評(píng)論已更新。',
           ]);
   }

刪除酒店評(píng)論數(shù)據(jù)

    /**
    * 刪除酒店評(píng)論數(shù)據(jù)的功能測(cè)試
    *
    * @return 無效
    */
   公共功能 test_for_delete_hotel_review()
   {
       $user = 用戶::創(chuàng)建([
           '名稱' => 蘭德(),
           '電子郵件' => 蘭德()。' .abc@xyz.com ',
           'created_at' => Carbon::now(),
           'updated_at' => Carbon::now(),
       ]);
     
       $酒店=酒店::創(chuàng)建([
           '名稱' => 蘭德(),
           '明星'=> 2,
           'address' => '市政廳對(duì)面,Nr。Sakar II & IV, Ashram Rd, Ellisbridge, Ahmedabad, Gujarat 380006',
           '活動(dòng)'=> 0,
           'created_at' => Carbon::now(),
           'updated_at' => Carbon::now(),
       ]);

       $hotelReview = 評(píng)論::創(chuàng)建([
           'title' => '好萊塢好酒店',
           'description' => 'HollywoodInn 是一家非常不錯(cuò)的酒店。',
           'user_id' => $user->id,
           'hotel_id' => $hotel->id,
           'created_at' => Carbon::now(),
           'updated_at' => Carbon::now(),
       ]);

       $this->json('DELETE', 'api/review/' . $hotelReview->id)
           ->assertStatus(200)
           ->assertJson([
               '代碼'=>'200',
               'message' => '酒店評(píng)論刪除成功。',
           ]);
    }

存儲(chǔ)新的審核所需數(shù)據(jù)

    /**
    * 存儲(chǔ)新審核所需數(shù)據(jù)的功能測(cè)試
    *
    * @return 無效
    */
   公共功能 test_for_add_hotel_review_required_fields()
   {
       $this->json('POST', 'api/save-hotel-review')
           ->assertStatus(200)
           ->assertJson([
               '代碼'=>'401',
               'message' => '酒店 ID 字段是必需的。用戶 ID 字段是必需的。評(píng)論標(biāo)題字段是必需的。評(píng)論數(shù)據(jù)字段是必需的,
           ]);
   }

更新審核所需數(shù)據(jù)

    /**
    * 更新審核所需數(shù)據(jù)的功能測(cè)試
    *
    * @return 無效
    */
   公共功能 test_for_update_hotel_review_required_fields()
   {
       $user = 用戶::創(chuàng)建([
           '名稱' => 蘭德(),
           '電子郵件' => 蘭德()。' .abc@xyz.com ',
           'created_at' => Carbon::now(),
           'updated_at' => Carbon::now(),
       ]);
       //$user = User::create($userData);
       $酒店=酒店::創(chuàng)建([
           '名稱' => 蘭德(),
           '明星'=> 2,
           'address' => '市政廳對(duì)面,Nr。Sakar II & IV, Ashram Rd, Ellisbridge, Ahmedabad, Gujarat 380006',
           '活動(dòng)'=> 0,
           'created_at' => Carbon::now(),
           'updated_at' => Carbon::now(),
       ]);
       //$hotel = User::create($hotelData);
       $hotelReview = 評(píng)論::創(chuàng)建([
           'title' => '好萊塢好酒店',
           'description' => 'HollywoodInn 是一家非常不錯(cuò)的酒店。',
           'user_id' => $user->id,
           'hotel_id' => $hotel->id,
           'created_at' => Carbon::now(),
           'updated_at' => Carbon::now(),
       ]);

       $this->json('PUT', 'api/update-hotel-review/' . $hotelReview->id)
           ->assertStatus(200)
           ->assertJson([
               '代碼'=>'401',
               'message' => '酒店 ID 字段是必需的。用戶 ID 字段是必需的。評(píng)論標(biāo)題字段是必需的。評(píng)論數(shù)據(jù)字段是必需的,
        ]);
   }

更新不存在的評(píng)論

    /**
    * 更新不存在的評(píng)論的功能測(cè)試
    *
    * @return 無效
    */
   公共功能 test_for_update_hotel_review_that_not_exist()
   {
       //數(shù)據(jù)庫中不存在的評(píng)論id
       $reviewId = random_int(100000, 999999);
       $有效載荷= [
           "hotel_id" => random_int(100, 999),
           "user_id" => random_int(100, 999),
           "review_title" => "測(cè)試",
           “review_data”=>“測(cè)試說明”
       ];
       $this->json('PUT', 'api/update-hotel-review/' . $reviewId, $payload)
           ->assertStatus(200)
           ->assertJson([
               '代碼'=>'401',
               'message' => '無效的酒店 ID 或用戶 ID 或評(píng)論 ID',
           ]);
   }

刪除不存在的評(píng)論

    /**
    * 刪除不存在的評(píng)論的功能測(cè)試
    *
    * @return 無效
    */
   公共功能 test_for_delete_review_that_not_exist()
   {
       //數(shù)據(jù)庫中不存在的評(píng)論id
       $reviewId = random_int(100000, 999999);

       $this->json('DELETE', 'api/review/' . $reviewId)
           ->assertStatus(200)
           ->assertJson([
               '代碼'=>'401',
               'message' => '沒有找到評(píng)論,請(qǐng)重試',
           ]);
   }}

解釋

  • test_get_all_active_hotels() 是為應(yīng)用程序運(yùn)行測(cè)試的主要函數(shù)。現(xiàn)在,我們?cè)谶@個(gè)函數(shù)中測(cè)試什么?它測(cè)試所有活躍酒店的數(shù)據(jù),這些數(shù)據(jù)將由端點(diǎn) /api/hotels 返回。

  • $this->get('/api/hotels') 獲取酒店數(shù)據(jù)

  • ->assertStatus(200) 驗(yàn)證從 API 返回的 HTTP 狀態(tài)代碼。

  • ->assertJsonStructure( … ); 驗(yàn)證端點(diǎn)返回的響應(yīng)的 JSON 結(jié)構(gòu)。下面是 API 的示例響應(yīng)。

{
   “代碼”:“200”,
   "message": "酒店數(shù)據(jù)",
   “數(shù)據(jù)”: [
       {
           “編號(hào)”:1,
           "name": "海亞特",
           “地址”:“17/A, Ashram Rd, Usmanpura, Ahmedabad, Gujarat 380014”,
           “星”:4,
           "create_at": "11/Jan/2022 15:40:56",
           "update_at": "11/Jan/2022 15:40:56",
           “活躍”:“活躍”,
           “審查”: [
               {
                   “編號(hào)”:2,
                   "title": "凱悅酒店",
                   "description": "Hyaat 是一家非常不錯(cuò)的酒店。",
                   “作者”:“帕特”,
                   "create_at": "11/Jan/2022 15:40:56",
                   “update_at”:“2022 年 1 月 11 日 15:40:56”
               }
           ]
       },
  ]    }
  • test_get_active_hotel_by_id根據(jù)酒店ID驗(yàn)證酒店點(diǎn)評(píng)數(shù)據(jù)。

  • test_for_get_inactive_hotel_by_id在傳遞非活動(dòng)酒店 ID 時(shí)驗(yàn)證酒店評(píng)論數(shù)據(jù)。

  • test_for_add_hotel_review在所有數(shù)據(jù)都通過 valid 時(shí)驗(yàn)證添加酒店評(píng)論功能

  • 當(dāng)所有數(shù)據(jù)通過有效時(shí),函數(shù)test_for_update_hotel_review驗(yàn)證更新后的酒店評(píng)論功能

  • 函數(shù)test_for_delete_hotel_review在傳遞有效酒店評(píng)論 ID 時(shí)驗(yàn)證刪除酒店評(píng)論功能。

  • 函數(shù)test_for_add_hotel_review_required_fields在調(diào)用添加新酒店評(píng)論 API 時(shí)沒有數(shù)據(jù)通過時(shí)驗(yàn)證必填字段驗(yàn)證。

  • 函數(shù)test_for_update_hotel_review_required_fields在更新調(diào)用的新酒店評(píng)論 API 時(shí)沒有數(shù)據(jù)通過時(shí)驗(yàn)證必填字段驗(yàn)證。

  • 函數(shù)test_for_update_hotel_review_that_not_exist驗(yàn)證通過的酒店評(píng)論 ID 在更新酒店評(píng)論功能的數(shù)據(jù)庫中不存在的情況。

  • 函數(shù)test_for_delete_review_that_not_exist驗(yàn)證通過的酒店評(píng)論 ID 在刪除酒店評(píng)論功能的數(shù)據(jù)庫中不存在的情況。

  • 其他 assertJson 如下

  •      ->assertJson([
              '代碼'=>'401',
               'message' => '沒有找到評(píng)論,請(qǐng)重試',
          ]);

    assertJson 測(cè)試 JSON 結(jié)果是否符合我們的預(yù)期意味著從 API 返回相同的輸出 JSON,就像比較兩個(gè)字符串一樣。

    • assertTrue() 和 assertFalse()

    assertTrue() 和 assertFalse() 允許您斷言一個(gè)值等于 true 或 false。這意味著它們非常適合測(cè)試返回布爾值的方法。

    • assertEquals() 和 assertNull()

    assertEquals() 用于比較變量的實(shí)際值和期望值。與 assertTrue()、assertFalse() 和 assertNull() 不同,assertEquals() 有兩個(gè)參數(shù)。第一個(gè)是期望值,第二個(gè)是實(shí)際值。

    • assertContains()、assertCount() 和 assertEmpty()

    assertContains() 斷言提供的數(shù)組中存在預(yù)期值,assertCount() 斷言數(shù)組中的項(xiàng)目數(shù)與指定的數(shù)量匹配,assertEmpty() 斷言提供的數(shù)組為空。

    訪問Laravel 文檔以了解其他功能。

    運(yùn)行測(cè)試用例

    在根文件夾中使用以下命令運(yùn)行測(cè)試用例。

    php工匠測(cè)試

    Github 存儲(chǔ)庫:Laravel 示例中的功能測(cè)試

    您可以訪問源代碼并克隆存儲(chǔ)庫以使用代碼。

    結(jié)論

    我希望在 Laravel 中針對(duì) REST API 實(shí)施功能測(cè)試的教程能夠如您所愿地為您服務(wù)。我們?yōu)橄衲@樣的愛好者準(zhǔn)備了幾個(gè) Laravel 教程。如果您想學(xué)習(xí)和探索有關(guān) Laravel 的更多信息,請(qǐng)?jiān)L問Laravel 教程頁面。

言鼎科技

The End