在 Laravel 中为 REST API 实施功能测试

yanding 2023-06-12 207

介绍

使用测试用例会让您感到害怕吗?您是否正在寻找一个简单的教程来开始在 Laravel 中进行功能测试?然后,我们坚持让您坚持这个循序渐进的指南,以消除您的疑虑并学习在 Laravel 应用程序中进行测试。

Laravel 中的功能测试:什么、为什么以及如何?

Laravel 中的功能测试是什么?

在开发应用程序时,您往往会担心在执行功能或模块时代码会被破坏。为了避免出现这种情况,在您的应用程序中实施测试很重要。

特性测试是最常用和最重要的测试类型之一。它允许您测试应用程序代码的主要部分,这些代码具有相互交互的对象、HTTP 请求、JSON 等。

为什么在 Laravel 中进行功能测试?

  • 使工作顺畅

  • 避免破坏整个应用程序

  • 代码可维护性

  • 应用稳定性

  • 应用程序崩溃时轻松调试

  • 轻松确定应用程序崩溃背后的原因

最好的部分是测试是自动化的。它会发现代码中的漏洞并允许您正确开发功能。

Laravel 中的特性测试是如何工作的?

Laravel 支持 PHPUnit 测试。您的 Web 应用程序附带一个 phpunit.xml 文件,其中包含测试 Laravel 应用程序所需的所有设置。您的 phpunit.xml 文件设置了用于测试的 laravel 环境。因此无需创建新的 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="供应商/autoload.php"
        颜色=“真”>
   <测试套件>
       <测试套件名称="单元">
           <目录后缀="Test.php">./tests/Unit</directory>
       </测试套件>
       <测试套件名称="功能">
           <目录后缀="Test.php">./tests/Feature</directory>
       </测试套件>
   </测试套件>
   <覆盖过程UncoveredFiles="true">
       <包括>
           <目录后缀=".php">./app</directory>
       </include>
   </覆盖>
   <php>
       <server name="APP_ENV" value="testing"/>
       <服务器名称="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>

初始设置

对于本教程,我们将使用酒店评论 api。终端用户可以对酒店进行点评,可以对酒店点评进行添加、更新、删除以及酒店点评列表操作。

通过以下命令创建 laravel 应用程序

作曲家创建项目 --prefer-dist laravel/laravel hotel_review_api_testcd hotel_review_api_test

打开 .env 文件并更新数据库详细信息。

DB_CONNECTION=mysqlDB_HOST=127.0.0.1DB_PORT=3306DB_DATABASE=hotel_test_apiDB_USERNAME=root数据库密码=

创建模型和迁移

对于模型,运行以下命令。

php artisan make:model 酒店php artisan make:model 评论

对于迁移,请运行以下命令。

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

发展。维持。优化。部署 - 与 Bacancy!
您是否正在寻找熟练的开发人员来构建高度优化的应用程序?与我们联系以聘请 Laravel 开发人员。联系最好的,得到最好的!时期!

创建数据库表

现在通过下面提到的代码更新迁移文件。

我们将更新用户表、酒店表和评论表文件。按照指示添加列。您可以根据需要编辑列。

用户表

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

酒店餐桌

公共功能向上(){
 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';
    $表->时间戳();
    $表->softDeletes();
 });}

审查表

公共功能向上(){
  Schema::create('reviews', function (Blueprint $table) {
     $table->bigIncrements('id')->unsinged();
     $table->string('标题', 100);
     $table->text('描述', 100);
     $table->unsignedBigInteger('user_id')->nullable();
     $table->unsignedBigInteger('hotel_id')->nullable();
     $表->时间戳();$表->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');
  });
}

运行迁移

php 工匠迁移

生成 API 路由和 CRUD 业务逻辑

打开 \routes\api.php 并使用以下代码片段为我们的 API 生成路由。我们将有五个 API。

路线\ api.php

// 获取所有活跃的酒店数据Route::get('酒店', [HotelController::class,'getAllHotelData']);
// 获取特定酒店数据Route::get('hotel/{hotel_id}', [HotelController::class,'getHotelDataById']);
// 添加新的酒店评论Route::post('save-hotel-review', [HotelController::class,'storeHotelReviewData']);
// 更新酒店评论Route::put('update-hotel-review/{review_id}', [HotelController::class,'updateHotelReviewData']);
// 删除酒店评论Route::delete('review/{review_id}', [HotelController::class,'deleteHotelReview']);

增删改查业务逻辑

对于CRUD操作的业务逻辑,新建一个HotelController.php文件。我们不会指定 API 的代码片段。但是如果您想看一下,这里是指向HotelController.php的 Github 链接。我们将遵循这五个 API。

  • /api/hotels: 返回所有酒店数据

  • /api/hotel/{hotel_id}:返回特定酒店的数据

  • /api/save-hotel-review: 添加酒店评论

  • /api/update-hotel-review/{review_id}:更新酒店评论

  • /api/review/{review_id}: 删除酒店评论

在 Laravel 应用程序中创建功能测试

本节将为我们的应用程序创建我们的第一个功能测试。运行以下命令以生成一个名为 HotelTest 的用于测试的文件。

php artisan make:test HotelTest

该命令将使用以下代码在测试 > 功能文件夹中创建一个名为 HotelTest.php 的新文件。

断言真(真);
   }}

更新 HotelTest.php

我们将为应用程序的每个单元编写测试。我们进行了书面测试以确保:可以添加、删除、更新和列出有效的酒店评论。使用以下代码更新HotelTest.php 。

<?php
命名空间测试\功能;
使用测试\测试用例;使用 App\Models\Hotel;使用 App\Models\User;使用 App\Models\Review;使用碳\碳;

获取特定酒店的活跃酒店数据

类 HotelTest 扩展了 TestCase{
   /**
    * 基于酒店ID获取活跃酒店数据的功能测试
    *
    * @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(
               [
                   '代码',
                   '信息',
                   '数据'=> [
                       'ID',
                       '姓名',
                       '星星',
                       '评论'=> [
                           '*' => [
                               “ID”,
                               “标题”,
                               “描述”,
                               “作者”,
                               “创建”,
                               “更新时间”
                           ],
                       ]
                   ],
               ]
           );
   }

获取所有活跃的酒店数据

    /**
    * 获取所有活跃酒店数据的功能测试
    *
    * @return 无效
    */
   公共功能 test_get_all_active_hotels()
   {
       $response = $this->get('/api/hotels')
           ->assertStatus(200)
           ->assertJsonStructure(
               [
                   '代码',
                   '信息',
                   '数据'=> [
                       '*' => [
                           “ID”,
                           “姓名”,
                           “地址”,
                           “星星”,
                           “创建”,
                           “更新时间”,
                           “积极的”,
                           “评论”=> [
                               '*' => [
                                   “ID”,
                                   “标题”,
                                   “描述”,
                                   “作者”,
                                   “创建”,
                                   “更新时间”
                               ],
                           ],
                       ],
                   ],
               ]
           );
   }

获取特定酒店的所有非活动酒店数据

   /**
    * 基于酒店ID获取非活跃酒店数据的功能测试
    *
    * @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(
               [
                   '代码',
                   '信息',
               ]
           );
   }

添加新评论

    /**
    * 添加新评论的功能测试
    *
    * @return 无效
    */
   公共功能 test_for_add_hotel_review()
   {
       $user = 用户::创建([
           '名称' => 兰德(),
           '电子邮件' => 兰德()。' .abc@xyz.com ',
           'created_at' => Carbon::now(),
           'updated_at' => Carbon::now(),
       ]);
       //$user = User::create($userData);
       $酒店=酒店::创建([
           '名称' => 兰德(),
           '明星'=> 2,
           'address' => '市政厅对面,Nr。Sakar II & IV, Ashram Rd, Ellisbridge, Ahmedabad, Gujarat 380006',
           '活动'=> 0,
           'created_at' => Carbon::now(),
           'updated_at' => Carbon::now(),
       ]);

       $有效载荷= [
           "hotel_id" => $hotel->id,
           "user_id" => $user->id,
           "review_title" => "测试",
           “review_data”=>“测试说明”
       ];

       $this->json('POST', 'api/save-hotel-review', $payload)
           ->assertStatus(200)
           ->assertJson([
               '代码'=>'200',
               'message' => '酒店评论已保存。',
           ]);
   }

更新具体评论

    /**
    * 基于评论 ID 更新评论的功能测试
    *
    * @return 无效
    */
   公共功能 test_for_update_hotel_review()
   {
       $user = 用户::创建([
           '名称' => 兰德(),
           '电子邮件' => 兰德()。' .abc@xyz.com ',
           'created_at' => Carbon::now(),
           'updated_at' => Carbon::now(),
       ]);
       //$user = User::create($userData);
       $酒店=酒店::创建([
           '名称' => 兰德(),
           '明星'=> 2,
           'address' => '市政厅对面,Nr。Sakar II & IV, Ashram Rd, Ellisbridge, Ahmedabad, Gujarat 380006',
           '活动'=> 0,
           'created_at' => Carbon::now(),
           'updated_at' => Carbon::now(),
       ]);

       $hotelReview = 评论::创建([
           'title' => '好莱坞好酒店',
           'description' => 'HollywoodInn 是一家非常不错的酒店。',
           '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" => "测试",
           “review_data”=>“测试说明”
       ];

       $this->json('PUT', 'api/update-hotel-review/' . $hotelReview->id, $payload)
           ->assertStatus(200)
           ->assertJson([
               '代码'=>'200',
               'message' => '酒店评论已更新。',
           ]);
   }

删除酒店评论数据

    /**
    * 删除酒店评论数据的功能测试
    *
    * @return 无效
    */
   公共功能 test_for_delete_hotel_review()
   {
       $user = 用户::创建([
           '名称' => 兰德(),
           '电子邮件' => 兰德()。' .abc@xyz.com ',
           'created_at' => Carbon::now(),
           'updated_at' => Carbon::now(),
       ]);
     
       $酒店=酒店::创建([
           '名称' => 兰德(),
           '明星'=> 2,
           'address' => '市政厅对面,Nr。Sakar II & IV, Ashram Rd, Ellisbridge, Ahmedabad, Gujarat 380006',
           '活动'=> 0,
           'created_at' => Carbon::now(),
           'updated_at' => Carbon::now(),
       ]);

       $hotelReview = 评论::创建([
           'title' => '好莱坞好酒店',
           'description' => 'HollywoodInn 是一家非常不错的酒店。',
           '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' => '酒店评论删除成功。',
           ]);
    }

存储新的审核所需数据

    /**
    * 存储新审核所需数据的功能测试
    *
    * @return 无效
    */
   公共功能 test_for_add_hotel_review_required_fields()
   {
       $this->json('POST', 'api/save-hotel-review')
           ->assertStatus(200)
           ->assertJson([
               '代码'=>'401',
               'message' => '酒店 ID 字段是必需的。用户 ID 字段是必需的。评论标题字段是必需的。评论数据字段是必需的,
           ]);
   }

更新审核所需数据

    /**
    * 更新审核所需数据的功能测试
    *
    * @return 无效
    */
   公共功能 test_for_update_hotel_review_required_fields()
   {
       $user = 用户::创建([
           '名称' => 兰德(),
           '电子邮件' => 兰德()。' .abc@xyz.com ',
           'created_at' => Carbon::now(),
           'updated_at' => Carbon::now(),
       ]);
       //$user = User::create($userData);
       $酒店=酒店::创建([
           '名称' => 兰德(),
           '明星'=> 2,
           'address' => '市政厅对面,Nr。Sakar II & IV, Ashram Rd, Ellisbridge, Ahmedabad, Gujarat 380006',
           '活动'=> 0,
           'created_at' => Carbon::now(),
           'updated_at' => Carbon::now(),
       ]);
       //$hotel = User::create($hotelData);
       $hotelReview = 评论::创建([
           'title' => '好莱坞好酒店',
           'description' => 'HollywoodInn 是一家非常不错的酒店。',
           '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 字段是必需的。评论标题字段是必需的。评论数据字段是必需的,
        ]);
   }

更新不存在的评论

    /**
    * 更新不存在的评论的功能测试
    *
    * @return 无效
    */
   公共功能 test_for_update_hotel_review_that_not_exist()
   {
       //数据库中不存在的评论id
       $reviewId = random_int(100000, 999999);
       $有效载荷= [
           "hotel_id" => random_int(100, 999),
           "user_id" => random_int(100, 999),
           "review_title" => "测试",
           “review_data”=>“测试说明”
       ];
       $this->json('PUT', 'api/update-hotel-review/' . $reviewId, $payload)
           ->assertStatus(200)
           ->assertJson([
               '代码'=>'401',
               'message' => '无效的酒店 ID 或用户 ID 或评论 ID',
           ]);
   }

删除不存在的评论

    /**
    * 删除不存在的评论的功能测试
    *
    * @return 无效
    */
   公共功能 test_for_delete_review_that_not_exist()
   {
       //数据库中不存在的评论id
       $reviewId = random_int(100000, 999999);

       $this->json('DELETE', 'api/review/' . $reviewId)
           ->assertStatus(200)
           ->assertJson([
               '代码'=>'401',
               'message' => '没有找到评论,请重试',
           ]);
   }}

解释

  • test_get_all_active_hotels() 是为应用程序运行测试的主要函数。现在,我们在这个函数中测试什么?它测试所有活跃酒店的数据,这些数据将由端点 /api/hotels 返回。

  • $this->get('/api/hotels') 获取酒店数据

  • ->assertStatus(200) 验证从 API 返回的 HTTP 状态代码。

  • ->assertJsonStructure( … ); 验证端点返回的响应的 JSON 结构。下面是 API 的示例响应。

{
   “代码”:“200”,
   "message": "酒店数据",
   “数据”: [
       {
           “编号”: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",
           “活跃”:“活跃”,
           “审查”: [
               {
                   “编号”:2,
                   "title": "凯悦酒店",
                   "description": "Hyaat 是一家非常不错的酒店。",
                   “作者”:“帕特”,
                   "create_at": "11/Jan/2022 15:40:56",
                   “update_at”:“2022 年 1 月 11 日 15:40:56”
               }
           ]
       },
  ]    }
  • test_get_active_hotel_by_id根据酒店ID验证酒店点评数据。

  • test_for_get_inactive_hotel_by_id在传递非活动酒店 ID 时验证酒店评论数据。

  • test_for_add_hotel_review在所有数据都通过 valid 时验证添加酒店评论功能

  • 当所有数据通过有效时,函数test_for_update_hotel_review验证更新后的酒店评论功能

  • 函数test_for_delete_hotel_review在传递有效酒店评论 ID 时验证删除酒店评论功能。

  • 函数test_for_add_hotel_review_required_fields在调用添加新酒店评论 API 时没有数据通过时验证必填字段验证。

  • 函数test_for_update_hotel_review_required_fields在更新调用的新酒店评论 API 时没有数据通过时验证必填字段验证。

  • 函数test_for_update_hotel_review_that_not_exist验证通过的酒店评论 ID 在更新酒店评论功能的数据库中不存在的情况。

  • 函数test_for_delete_review_that_not_exist验证通过的酒店评论 ID 在删除酒店评论功能的数据库中不存在的情况。

  • 其他 assertJson 如下

  •      ->assertJson([
              '代码'=>'401',
               'message' => '没有找到评论,请重试',
          ]);

    assertJson 测试 JSON 结果是否符合我们的预期意味着从 API 返回相同的输出 JSON,就像比较两个字符串一样。

    • assertTrue() 和 assertFalse()

    assertTrue() 和 assertFalse() 允许您断言一个值等于 true 或 false。这意味着它们非常适合测试返回布尔值的方法。

    • assertEquals() 和 assertNull()

    assertEquals() 用于比较变量的实际值和期望值。与 assertTrue()、assertFalse() 和 assertNull() 不同,assertEquals() 有两个参数。第一个是期望值,第二个是实际值。

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

    assertContains() 断言提供的数组中存在预期值,assertCount() 断言数组中的项目数与指定的数量匹配,assertEmpty() 断言提供的数组为空。

    访问Laravel 文档以了解其他功能。

    运行测试用例

    在根文件夹中使用以下命令运行测试用例。

    php工匠测试

    Github 存储库:Laravel 示例中的功能测试

    您可以访问源代码并克隆存储库以使用代码。

    结论

    我希望在 Laravel 中针对 REST API 实施功能测试的教程能够如您所愿地为您服务。我们为像您这样的爱好者准备了几个 Laravel 教程。如果您想学习和探索有关 Laravel 的更多信息,请访问Laravel 教程页面

言鼎科技

The End