在 Laravel 中為 REST API 實(shí)施功能測(cè)試
介紹
使用測(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 如下
assertTrue() 和 assertFalse()
assertEquals() 和 assertNull()
assertContains()、assertCount() 和 assertEmpty()
->assertJson([
'代碼'=>'401',
'message' => '沒有找到評(píng)論,請(qǐng)重試',
]);
assertJson 測(cè)試 JSON 結(jié)果是否符合我們的預(yù)期意味著從 API 返回相同的輸出 JSON,就像比較兩個(gè)字符串一樣。
assertTrue() 和 assertFalse() 允許您斷言一個(gè)值等于 true 或 false。這意味著它們非常適合測(cè)試返回布爾值的方法。
assertEquals() 用于比較變量的實(shí)際值和期望值。與 assertTrue()、assertFalse() 和 assertNull() 不同,assertEquals() 有兩個(gè)參數(shù)。第一個(gè)是期望值,第二個(gè)是實(shí)際值。
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 教程頁面。