HTTP 測試
簡介
Laravel 提供了一個非常流暢的 API,用於向您的應用程式發送 HTTP 請求並檢查回應。例如,請看下面定義的功能測試 (feature test):
<?php
test('the application returns a successful response', function () {
$response = $this->get('/');
$response->assertStatus(200);
});<?php
namespace Tests\Feature;
use Tests\TestCase;
class ExampleTest extends TestCase
{
/**
* A basic test example.
*/
public function test_the_application_returns_a_successful_response(): void
{
$response = $this->get('/');
$response->assertStatus(200);
}
}get 方法向應用程式發送一個 GET 請求,而 assertStatus 方法則斷言回傳的回應應具有指定的 HTTP 狀態碼。除了這個簡單的斷言之外,Laravel 還包含各種用於檢查回應標頭、內容、JSON 結構等項目的斷言。
發送請求
若要向您的應用程式發送請求,您可以在測試中調用 get、post、put、patch 或 delete 方法。這些方法並不會真的對您的應用程式發出「真實的」HTTP 請求,而是在內部模擬整個網路請求。
測試請求方法不會回傳 Illuminate\Http\Response 實例,而是回傳 Illuminate\Testing\TestResponse 的實例,它提供了多種實用的斷言,讓您可以檢查應用程式的回應:
<?php
test('basic request', function () {
$response = $this->get('/');
$response->assertStatus(200);
});<?php
namespace Tests\Feature;
use Tests\TestCase;
class ExampleTest extends TestCase
{
/**
* A basic test example.
*/
public function test_a_basic_request(): void
{
$response = $this->get('/');
$response->assertStatus(200);
}
}一般來說,您的每個測試應該只對應用程式發送一個請求。如果在單個測試方法中執行多個請求,可能會發生非預期的行為。
📌 備註
為了方便起見,在執行測試時會自動停用 CSRF 中介層。
自訂請求標頭
您可以使用 withHeaders 方法在請求發送到應用程式之前自訂其標頭。此方法允許您在請求中加入任何您想要的自訂標頭:
<?php
test('interacting with headers', function () {
$response = $this->withHeaders([
'X-Header' => 'Value',
])->post('/user', ['name' => 'Sally']);
$response->assertStatus(201);
});<?php
namespace Tests\Feature;
use Tests\TestCase;
class ExampleTest extends TestCase
{
/**
* A basic functional test example.
*/
public function test_interacting_with_headers(): void
{
$response = $this->withHeaders([
'X-Header' => 'Value',
])->post('/user', ['name' => 'Sally']);
$response->assertStatus(201);
}
}Cookies
您可以在發送請求之前使用 withCookie 或 withCookies 方法設定 Cookie 的值。withCookie 方法接受 Cookie 名稱與值作為其兩個參數,而 withCookies 方法則接受一個名稱/值對的陣列:
<?php
test('interacting with cookies', function () {
$response = $this->withCookie('color', 'blue')->get('/');
$response = $this->withCookies([
'color' => 'blue',
'name' => 'Taylor',
])->get('/');
//
});<?php
namespace Tests\Feature;
use Tests\TestCase;
class ExampleTest extends TestCase
{
public function test_interacting_with_cookies(): void
{
$response = $this->withCookie('color', 'blue')->get('/');
$response = $this->withCookies([
'color' => 'blue',
'name' => 'Taylor',
])->get('/');
//
}
}Session / 認證
Laravel 提供了幾個輔助方法,用於在 HTTP 測試期間與 Session 進行互動。首先,您可以使用 withSession 方法將指定的陣列設定為 Session 資料。這在向應用程式發送請求之前預載 Session 資料非常有用:
<?php
test('interacting with the session', function () {
$response = $this->withSession(['banned' => false])->get('/');
//
});<?php
namespace Tests\Feature;
use Tests\TestCase;
class ExampleTest extends TestCase
{
public function test_interacting_with_the_session(): void
{
$response = $this->withSession(['banned' => false])->get('/');
//
}
}Laravel 的 Session 通常用於維持目前已認證使用者的狀態。因此,actingAs 輔助方法提供了一種簡單的方式,將指定的使用者認證為目前使用者。例如,我們可以使用 Model 工廠 來產生並認證一個使用者:
<?php
use App\Models\User;
test('an action that requires authentication', function () {
$user = User::factory()->create();
$response = $this->actingAs($user)
->withSession(['banned' => false])
->get('/');
//
});<?php
namespace Tests\Feature;
use App\Models\User;
use Tests\TestCase;
class ExampleTest extends TestCase
{
public function test_an_action_that_requires_authentication(): void
{
$user = User::factory()->create();
$response = $this->actingAs($user)
->withSession(['banned' => false])
->get('/');
//
}
}您也可以透過將 Guard 名稱作為第二個參數傳遞給 actingAs 方法,來指定應用於認證該使用者的 Guard。提供給 actingAs 方法的 Guard 也將在測試期間成為預設的 Guard:
$this->actingAs($user, 'web');如果您想確保請求是未經認證的,可以使用 actingAsGuest 方法:
$this->actingAsGuest();除錯回應
向您的應用程式發送測試請求後,可以使用 dump、dumpHeaders 與 dumpSession 方法來檢查並除錯回應內容:
<?php
test('basic test', function () {
$response = $this->get('/');
$response->dump();
$response->dumpHeaders();
$response->dumpSession();
});<?php
namespace Tests\Feature;
use Tests\TestCase;
class ExampleTest extends TestCase
{
/**
* A basic test example.
*/
public function test_basic_test(): void
{
$response = $this->get('/');
$response->dump();
$response->dumpHeaders();
$response->dumpSession();
}
}或者,您可以使用 dd、ddHeaders、ddBody、ddJson 與 ddSession 方法來印出關於回應的資訊並停止執行:
<?php
test('basic test', function () {
$response = $this->get('/');
$response->dd();
$response->ddHeaders();
$response->ddBody();
$response->ddJson();
$response->ddSession();
});<?php
namespace Tests\Feature;
use Tests\TestCase;
class ExampleTest extends TestCase
{
/**
* A basic test example.
*/
public function test_basic_test(): void
{
$response = $this->get('/');
$response->dd();
$response->ddHeaders();
$response->ddBody();
$response->ddJson();
$response->ddSession();
}
}例外處理
有時您可能需要測試應用程式是否拋出了特定的例外。為了達成這個目標,您可以透過 Exceptions Facade 來「模擬 (fake)」例外處理器。一旦模擬了例外處理器,您就可以利用 assertReported 和 assertNotReported 方法對請求期間拋出的例外進行斷言:
<?php
use App\Exceptions\InvalidOrderException;
use Illuminate\Support\Facades\Exceptions;
test('exception is thrown', function () {
Exceptions::fake();
$response = $this->get('/order/1');
// Assert an exception was thrown...
Exceptions::assertReported(InvalidOrderException::class);
// Assert against the exception...
Exceptions::assertReported(function (InvalidOrderException $e) {
return $e->getMessage() === 'The order was invalid.';
});
});<?php
namespace Tests\Feature;
use App\Exceptions\InvalidOrderException;
use Illuminate\Support\Facades\Exceptions;
use Tests\TestCase;
class ExampleTest extends TestCase
{
/**
* A basic test example.
*/
public function test_exception_is_thrown(): void
{
Exceptions::fake();
$response = $this->get('/');
// Assert an exception was thrown...
Exceptions::assertReported(InvalidOrderException::class);
// Assert against the exception...
Exceptions::assertReported(function (InvalidOrderException $e) {
return $e->getMessage() === 'The order was invalid.';
});
}
}assertNotReported 和 assertNothingReported 方法可用於斷言指定的例外在請求期間未被拋出,或者完全沒有拋出任何例外:
Exceptions::assertNotReported(InvalidOrderException::class);
Exceptions::assertNothingReported();您可以在發送請求前呼叫 withoutExceptionHandling 方法,來完全停用特定請求的例外處理:
$response = $this->withoutExceptionHandling()->get('/');此外,如果您想確保您的應用程式沒有使用 PHP 語言或您應用程式使用的函式庫中已棄用的功能,您可以在發送請求前呼叫 withoutDeprecationHandling 方法。當停用棄用處理時,棄用警告將被轉換為例外,進而導致您的測試失敗:
$response = $this->withoutDeprecationHandling()->get('/');assertThrows 方法可用於斷言指定閉包內的程式碼會拋出指定型別的例外:
$this->assertThrows(
fn () => (new ProcessOrder)->execute(),
OrderInvalid::class
);如果您想檢查並對拋出的例外進行斷言,您可以將閉包作為 assertThrows 方法的第二個引數:
$this->assertThrows(
fn () => (new ProcessOrder)->execute(),
fn (OrderInvalid $e) => $e->orderId() === 123;
);assertDoesntThrow 方法可用於斷言指定閉包內的程式碼不會拋出任何例外:
$this->assertDoesntThrow(fn () => (new ProcessOrder)->execute());測試 JSON API
Laravel 也提供了多個輔助方法來測試 JSON API 及其回應。例如,可以使用 json, getJson, postJson, putJson, patchJson, deleteJson 以及 optionsJson 方法,透過各種 HTTP 動詞發送 JSON 請求。你也可以輕鬆地將資料與標頭傳遞給這些方法。首先,讓我們寫一個測試來對 /api/user 發送 POST 請求,並斷言回傳了預期的 JSON 資料:
<?php
test('making an api request', function () {
$response = $this->postJson('/api/user', ['name' => 'Sally']);
$response
->assertStatus(201)
->assertJson([
'created' => true,
]);
});<?php
namespace Tests\Feature;
use Tests\TestCase;
class ExampleTest extends TestCase
{
/**
* A basic functional test example.
*/
public function test_making_an_api_request(): void
{
$response = $this->postJson('/api/user', ['name' => 'Sally']);
$response
->assertStatus(201)
->assertJson([
'created' => true,
]);
}
}此外,JSON 回應資料可以像陣列變數一樣從回應物件中存取,讓你方便地檢查 JSON 回應中回傳的個別數值:
expect($response['created'])->toBeTrue();$this->assertTrue($response['created']);📌 備註
assertJson 方法會將回應轉換為陣列,以驗證給定的陣列是否存在於應用程式回傳的 JSON 回應中。因此,即使 JSON 回應中還有其他屬性,只要給定的片段存在,此測試仍會通過。
斷言 JSON 完全符合
如前所述,assertJson 方法可用於斷言 JSON 回應中是否存在某個 JSON 片段。如果你想驗證給定的陣列是否與應用程式回傳的 JSON 完全符合,你應該使用 assertExactJson 方法:
<?php
test('asserting an exact json match', function () {
$response = $this->postJson('/user', ['name' => 'Sally']);
$response
->assertStatus(201)
->assertExactJson([
'created' => true,
]);
});<?php
namespace Tests\Feature;
use Tests\TestCase;
class ExampleTest extends TestCase
{
/**
* A basic functional test example.
*/
public function test_asserting_an_exact_json_match(): void
{
$response = $this->postJson('/user', ['name' => 'Sally']);
$response
->assertStatus(201)
->assertExactJson([
'created' => true,
]);
}
}<?php
test('asserting a json path value', function () {
$response = $this->postJson('/user', ['name' => 'Sally']);
$response
->assertStatus(201)
->assertJsonPath('team.owner.name', 'Darian');
});<?php
namespace Tests\Feature;
use Tests\TestCase;
class ExampleTest extends TestCase
{
/**
* A basic functional test example.
*/
public function test_asserting_a_json_paths_value(): void
{
$response = $this->postJson('/user', ['name' => 'Sally']);
$response
->assertStatus(201)
->assertJsonPath('team.owner.name', 'Darian');
}
}assertJsonPath 方法也接受一個 closure,可用於動態判斷斷言是否應該通過:
$response->assertJsonPath('team.owner.name', fn (string $name) => strlen($name) >= 3);如果你需要一次斷言多個 JSON 路徑,可以使用 assertJsonPaths 方法。每個路徑的預期值也可以是一個 closure:
$response->assertJsonPaths([
'team.owner.name' => 'Darian',
'team.owner.email' => fn (string $email) => str($email)->is('*@laravel.com'),
'team.members.0.name' => 'Sally',
]);你可以使用 assertJsonMissingPaths 方法來斷言回應中缺少多個 JSON 路徑:
$response->assertJsonMissingPaths([
'team.owner.password',
'team.members.0.api_token',
]);流暢地測試 JSON
Laravel 還提供了一種優雅的方式來流暢地測試應用程式的 JSON 回應。首先,將一個閉包傳遞給 assertJson 方法。此閉包將會收到一個 Illuminate\Testing\Fluent\AssertableJson 實例,可用於對應用程式回傳的 JSON 進行斷言。where 方法可用於對 JSON 的特定屬性進行斷言,而 missing 方法則可用於斷言 JSON 中缺少某個特定屬性:
use Illuminate\Testing\Fluent\AssertableJson;
test('fluent json', function () {
$response = $this->getJson('/users/1');
$response
->assertJson(fn (AssertableJson $json) =>
$json->where('id', 1)
->where('name', 'Victoria Faith')
->where('email', fn (string $email) => str($email)->is('[email protected]'))
->whereNot('status', 'pending')
->missing('password')
->etc()
);
});use Illuminate\Testing\Fluent\AssertableJson;
/**
* A basic functional test example.
*/
public function test_fluent_json(): void
{
$response = $this->getJson('/users/1');
$response
->assertJson(fn (AssertableJson $json) =>
$json->where('id', 1)
->where('name', 'Victoria Faith')
->where('email', fn (string $email) => str($email)->is('[email protected]'))
->whereNot('status', 'pending')
->missing('password')
->etc()
);
}理解 etc 方法
在上面的範例中,您可能已經注意到我們在斷言鏈的末尾呼叫了 etc 方法。此方法會告知 Laravel,JSON 物件上可能還存在其他屬性。如果不使用 etc 方法,當 JSON 物件上存在您未進行斷言的其他屬性時,測試將會失敗。
這種行為的初衷是為了防止您無意中在 JSON 回應中洩漏敏感資訊,它強制您必須明確地對屬性進行斷言,或透過 etc 方法明確允許額外的屬性。
然而,您應該意識到,在斷言鏈中不包含 etc 方法並不能確保不會有額外的屬性被新增到巢狀於 JSON 物件中的陣列內。etc 方法僅確保在呼叫 etc 方法的該層級中不存在額外的屬性。
斷言屬性是否存在
若要斷言屬性是否存在或缺失,您可以使用 has 與 missing 方法:
$response->assertJson(fn (AssertableJson $json) =>
$json->has('data')
->missing('message')
);此外,hasAll 與 missingAll 方法允許同時斷言多個屬性的存在或缺失:
$response->assertJson(fn (AssertableJson $json) =>
$json->hasAll(['status', 'data'])
->missingAll(['message', 'code'])
);您可以使用 hasAny 方法來確定給定屬性列表中是否至少存在一個屬性:
$response->assertJson(fn (AssertableJson $json) =>
$json->has('status')
->hasAny('data', 'message', 'code')
);對 JSON 集合進行斷言
您的路由通常會回傳包含多個項目的 JSON 回應,例如多個使用者:
Route::get('/users', function () {
return User::all();
});在這些情況下,我們可以使用流暢 JSON 物件的 has 方法來對回應中包含的使用者進行斷言。例如,讓我們斷言 JSON 回應包含三個使用者。接著,我們將使用 first 方法對集合中的第一個使用者進行一些斷言。first 方法接受一個閉包,該閉包接收另一個可斷言的 JSON 字串,我們可以用它來對 JSON 集合中的第一個物件進行斷言:
$response
->assertJson(fn (AssertableJson $json) =>
$json->has(3)
->first(fn (AssertableJson $json) =>
$json->where('id', 1)
->where('name', 'Victoria Faith')
->where('email', fn (string $email) => str($email)->is('[email protected]'))
->missing('password')
->etc()
)
);如果您想對 JSON 集合中的每個項目進行相同的斷言,可以使用 each 方法:
$response
->assertJson(fn (AssertableJson $json) =>
$json->has(3)
->each(fn (AssertableJson $json) =>
$json->whereType('id', 'integer')
->whereType('name', 'string')
->whereType('email', 'string')
->missing('password')
->etc()
)
);限制 JSON 集合斷言的作用域
有時,您的應用程式路由會回傳被分配了命名鍵值的 JSON 集合:
Route::get('/users', function () {
return [
'meta' => [...],
'users' => User::all(),
];
})測試這些路由時,您可以使用 has 方法來斷言集合中的項目數量。此外,您可以使用 has 方法來限制斷言鏈的作用域:
$response
->assertJson(fn (AssertableJson $json) =>
$json->has('meta')
->has('users', 3)
->has('users.0', fn (AssertableJson $json) =>
$json->where('id', 1)
->where('name', 'Victoria Faith')
->where('email', fn (string $email) => str($email)->is('[email protected]'))
->missing('password')
->etc()
)
);然而,除了分兩次呼叫 has 方法來對 users 集合進行斷言外,您也可以進行單次呼叫,並將閉包作為其第三個參數提供。這樣做時,該閉包將自動被呼叫,並將作用域限制在集合中的第一個項目:
$response
->assertJson(fn (AssertableJson $json) =>
$json->has('meta')
->has('users', 3, fn (AssertableJson $json) =>
$json->where('id', 1)
->where('name', 'Victoria Faith')
->where('email', fn (string $email) => str($email)->is('[email protected]'))
->missing('password')
->etc()
)
);斷言 JSON 型別
您可能只想斷言 JSON 回應中的屬性屬於某種特定型別。Illuminate\Testing\Fluent\AssertableJson 類別提供了 whereType 與 whereAllType 方法來實現此目的:
$response->assertJson(fn (AssertableJson $json) =>
$json->whereType('id', 'integer')
->whereAllType([
'users.0.name' => 'string',
'meta' => 'array'
])
);您可以使用 | 字元指定多個型別,或將型別陣列作為 whereType 方法的第二個參數傳遞。如果回應值是列出的任何型別之一,斷言將成功:
$response->assertJson(fn (AssertableJson $json) =>
$json->whereType('name', 'string|null')
->whereType('id', ['string', 'integer'])
);whereType 與 whereAllType 方法可辨識以下型別:string、integer、double、boolean、array 以及 null。
測試檔案上傳
Illuminate\Http\UploadedFile 類別提供了一個 fake 方法,可用於產生測試用的虛擬檔案或圖片。將此方法與 Storage Facade 的 fake 方法結合使用,可以大幅簡化檔案上傳的測試。例如,您可以結合這兩個功能來輕鬆測試大頭照上傳表單:
<?php
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
test('avatars can be uploaded', function () {
Storage::fake('avatars');
$file = UploadedFile::fake()->image('avatar.jpg');
$response = $this->post('/avatar', [
'avatar' => $file,
]);
Storage::disk('avatars')->assertExists($file->hashName());
});<?php
namespace Tests\Feature;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;
class ExampleTest extends TestCase
{
public function test_avatars_can_be_uploaded(): void
{
Storage::fake('avatars');
$file = UploadedFile::fake()->image('avatar.jpg');
$response = $this->post('/avatar', [
'avatar' => $file,
]);
Storage::disk('avatars')->assertExists($file->hashName());
}
}如果您想斷言指定的檔案不存在,可以使用 Storage Facade 提供的 assertMissing 方法:
Storage::fake('avatars');
// ...
Storage::disk('avatars')->assertMissing('missing.jpg');偽造檔案自訂
使用 UploadedFile 類別提供的 fake 方法建立檔案時,您可以指定圖片的寬度、高度和大小(以 KB 為單位),以便更完整地測試應用程式的驗證規則:
UploadedFile::fake()->image('avatar.jpg', $width, $height)->size(100);除了建立圖片外,您還可以使用 create 方法建立任何其他類型的檔案:
UploadedFile::fake()->create('document.pdf', $sizeInKilobytes);如果需要,您可以向該方法傳遞一個 $mimeType 引數,以明確定義檔案應回傳的 MIME 類型:
UploadedFile::fake()->create(
'document.pdf', $sizeInKilobytes, 'application/pdf'
);測試視圖
Laravel 還允許您在不發送模擬 HTTP 請求的情況下渲染視圖。若要達成此目的,您可以在測試中呼叫 view 方法。view 方法接受視圖名稱和一個選用的資料陣列。該方法會回傳一個 Illuminate\Testing\TestView 實例,它提供了多種方法來方便地對視圖內容進行斷言:
<?php
test('a welcome view can be rendered', function () {
$view = $this->view('welcome', ['name' => 'Taylor']);
$view->assertSee('Taylor');
});<?php
namespace Tests\Feature;
use Tests\TestCase;
class ExampleTest extends TestCase
{
public function test_a_welcome_view_can_be_rendered(): void
{
$view = $this->view('welcome', ['name' => 'Taylor']);
$view->assertSee('Taylor');
}
}TestView 類別提供了以下斷言方法:assertSee、assertSeeInOrder、assertSeeText、assertSeeTextInOrder、assertDontSee 和 assertDontSeeText。
如果需要,您可以將 TestView 實例轉型為字串,以獲取原始渲染後的視圖內容:
$contents = (string) $this->view('welcome');共用錯誤
某些視圖可能依賴於 Laravel 提供的全域錯誤袋 (Error Bag) 中共用的錯誤。若要使用錯誤訊息填充錯誤袋,您可以使用 withViewErrors 方法:
$view = $this->withViewErrors([
'name' => ['Please provide a valid name.']
])->view('form');
$view->assertSee('Please provide a valid name.');渲染 Blade 與元件
如果有需要,您可以使用 blade 方法來解析並渲染原始的 Blade 字串。與 view 方法一樣,blade 方法也會回傳一個 Illuminate\Testing\TestView 實例:
$view = $this->blade(
'<x-component :name="$name" />',
['name' => 'Taylor']
);
$view->assertSee('Taylor');您可以使用 component 方法來解析並渲染 Blade 元件。component 方法會回傳一個 Illuminate\Testing\TestComponent 實例:
$view = $this->component(Profile::class, ['name' => 'Taylor']);
$view->assertSee('Taylor');快取路由
在測試執行之前,Laravel 會啟動一個全新的應用程式實例,包含收集所有定義的路由。如果您的應用程式有許多路由檔案,您可能希望在測試案例中加入 Illuminate\Foundation\Testing\WithCachedRoutes Trait。在使用此 Trait 的測試中,路由僅會被建立一次並儲存在記憶體中,這意味著路由收集程序在整個測試套件中只會執行一次:
<?php
use App\Http\Controllers\UserController;
use Illuminate\Foundation\Testing\WithCachedRoutes;
pest()->use(WithCachedRoutes::class);
test('basic example', function () {
$this->get(action([UserController::class, 'index']));
// ...
});<?php
namespace Tests\Feature;
use App\Http\Controllers\UserController;
use Illuminate\Foundation\Testing\WithCachedRoutes;
use Tests\TestCase;
class BasicTest extends TestCase
{
use WithCachedRoutes;
/**
* A basic functional test example.
*/
public function test_basic_example(): void
{
$response = $this->get(action([UserController::class, 'index']));
// ...
}
}可用的斷言
回應斷言
Laravel 的 Illuminate\Testing\TestResponse 類別提供了多種自訂斷言方法,供您在測試應用程式時使用。這些斷言可以透過 json、get、post、put 與 delete 測試方法回傳的回應來存取:
assertAcceptedassertBadRequestassertClientErrorassertConflictassertCookieassertCookieExpiredassertCookieNotExpiredassertCookieMissingassertCreatedassertDontSeeassertDontSeeTextassertDownloadassertExactJsonassertExactJsonStructureassertFailedDependencyassertForbiddenassertFoundassertGoneassertHeaderassertHeaderContainsassertHeaderMissingassertInternalServerErrorassertJsonassertJsonCountassertJsonFragmentassertJsonIsArrayassertJsonIsObjectassertJsonMissingassertJsonMissingExactassertJsonMissingValidationErrorsassertJsonPathassertJsonPathsassertJsonMissingPathassertJsonMissingPathsassertJsonStructureassertJsonValidationErrorsassertJsonValidationErrorForassertLocationassertMethodNotAllowedassertMovedPermanentlyassertContentassertNoContentassertStreamedassertStreamedContentassertNotFoundassertOkassertPaymentRequiredassertPlainCookieassertRedirectassertRedirectBackassertRedirectBackWithErrorsassertRedirectBackWithoutErrorsassertRedirectContainsassertRedirectToRouteassertRedirectToSignedRouteassertRequestTimeoutassertSeeassertSeeInOrderassertSeeTextassertSeeTextInOrderassertServerErrorassertServiceUnavailableassertSessionHasassertSessionHasInputassertSessionHasAllassertSessionHasErrorsassertSessionHasErrorsInassertSessionHasNoErrorsassertSessionDoesntHaveErrorsassertSessionMissingassertSessionMissingInputassertStatusassertSuccessfulassertTooManyRequestsassertUnauthorizedassertUnprocessableassertUnsupportedMediaTypeassertValidassertInvalidassertViewHasassertViewHasAllassertViewIsassertViewMissing
assertAccepted
斷言回應具有已接受 (202) 的 HTTP 狀態碼:
$response->assertAccepted();assertBadRequest
斷言回應具有錯誤請求 (400) 的 HTTP 狀態碼:
$response->assertBadRequest();assertClientError
斷言回應具有用戶端錯誤 (>= 400, < 500) 的 HTTP 狀態碼:
$response->assertClientError();assertConflict
斷言回應具有衝突 (409) 的 HTTP 狀態碼:
$response->assertConflict();assertCookie
斷言回應包含指定的 Cookie:
$response->assertCookie($cookieName, $value = null);assertCookieExpired
斷言回應包含指定的 Cookie 且該 Cookie 已過期:
$response->assertCookieExpired($cookieName);assertCookieNotExpired
斷言回應包含指定的 Cookie 且該 Cookie 尚未過期:
$response->assertCookieNotExpired($cookieName);assertCookieMissing
斷言回應不包含指定的 Cookie:
$response->assertCookieMissing($cookieName);assertCreated
斷言回應具有 201 HTTP 狀態碼:
$response->assertCreated();assertDontSee
斷言應用程式回傳的回應中不包含指定的字串。除非您將第二個引數傳遞為 false,否則此斷言會自動逸出指定的字串:
$response->assertDontSee($value, $escape = true);assertDontSeeText
斷言回應文字中不包含指定的字串。除非您將第二個引數傳遞為 false,否則此斷言會自動逸出指定的字串。此方法在進行斷言之前,會先將回應內容傳遞給 PHP 的 strip_tags 函式:
$response->assertDontSeeText($value, $escape = true);assertDownload
斷言回應是一個「下載」。通常這意味著被呼叫的路由回傳了 Response::download 回應、BinaryFileResponse 或 Storage::download 回應:
$response->assertDownload();如果您願意,可以斷言下載的檔案被指派了指定的檔名:
$response->assertDownload('image.jpg');assertExactJson
斷言回應包含與指定的 JSON 資料完全符合的內容:
$response->assertExactJson(array $data);assertExactJsonStructure
斷言回應包含與指定的 JSON 結構完全符合的內容:
$response->assertExactJsonStructure(array $data);此方法是 assertJsonStructure 的更嚴格變體。與 assertJsonStructure 不同,如果回應包含任何未明確包含在預期 JSON 結構中的鍵,此方法將會失敗。
assertFailedDependency
斷言回應具有相依性失敗 (424) 的 HTTP 狀態碼:
$response->assertFailedDependency();assertForbidden
斷言回應具有禁止存取 (403) 的 HTTP 狀態碼:
$response->assertForbidden();assertFound
斷言回應具有已尋獲 (302) 的 HTTP 狀態碼:
$response->assertFound();assertGone
斷言回應具有已消失 (410) 的 HTTP 狀態碼:
$response->assertGone();assertHeader
斷言回應中存在指定的標頭與值:
$response->assertHeader($headerName, $value = null);assertHeaderContains
斷言指定的標頭包含指定的子字串值:
$response->assertHeaderContains($headerName, $value);assertHeaderMissing
斷言回應中不存在指定的標頭:
$response->assertHeaderMissing($headerName);assertInternalServerError
斷言回應具有「內部伺服器錯誤」(500) 的 HTTP 狀態碼:
$response->assertInternalServerError();assertJson
斷言回應包含指定的 JSON 資料:
$response->assertJson(array $data, $strict = false);assertJson 方法會將回應轉換為陣列,以驗證指定的陣列是否存在於應用程式回傳的 JSON 回應中。因此,如果 JSON 回應中還有其他屬性,只要指定的片段存在,此測試仍會通過。
assertJsonCount
斷言回應的 JSON 中,在指定的鍵處具有包含預期項目數量的陣列:
$response->assertJsonCount($count, $key = null);assertJsonFragment
斷言回應中任何位置包含指定的 JSON 資料:
Route::get('/users', function () {
return [
'users' => [
[
'name' => 'Taylor Otwell',
],
],
];
});
$response->assertJsonFragment(['name' => 'Taylor Otwell']);assertJsonIsArray
斷言回應的 JSON 是一個陣列:
$response->assertJsonIsArray();assertJsonIsObject
斷言回應的 JSON 是一個物件:
$response->assertJsonIsObject();assertJsonMissing
斷言回應不包含指定的 JSON 資料:
$response->assertJsonMissing(array $data);assertJsonMissingExact
斷言回應不包含完全相同的 JSON 資料:
$response->assertJsonMissingExact(array $data);assertJsonMissingValidationErrors
斷言回應對於指定的鍵沒有 JSON 驗證錯誤:
$response->assertJsonMissingValidationErrors($keys);📌 備註
更通用的 assertValid 方法可用於斷言回應沒有以 JSON 回傳的驗證錯誤,且沒有將錯誤快閃到 Session 儲存空間。
assertJsonPath
斷言回應在指定路徑包含指定的資料:
$response->assertJsonPath($path, $expectedValue);例如,如果您的應用程式回傳以下 JSON 回應:
{
"user": {
"name": "Steve Schoger"
}
}您可以像這樣斷言 user 物件的 name 屬性符合指定的值:
$response->assertJsonPath('user.name', 'Steve Schoger');assertJsonPaths
斷言回應在多個指定路徑中包含指定的資料:
$response->assertJsonPaths(array $paths);例如,您可以一次斷言回應中的多個值:
$response->assertJsonPaths([
'user.name' => 'Steve Schoger',
'user.email' => fn (string $email) => str($email)->endsWith('@laravel.com'),
]);assertJsonMissingPath
斷言回應不包含指定路徑:
$response->assertJsonMissingPath($path);例如,如果您的應用程式回傳以下 JSON 回應:
{
"user": {
"name": "Steve Schoger"
}
}您可以斷言它不包含 user 物件的 email 屬性:
$response->assertJsonMissingPath('user.email');assertJsonMissingPaths
斷言回應不包含多個指定路徑:
$response->assertJsonMissingPaths($paths);例如,您可以斷言回應中缺少多個路徑:
$response->assertJsonMissingPaths([
'user.email',
'user.password',
]);assertJsonStructure
斷言回應具有指定的 JSON 結構:
$response->assertJsonStructure(array $structure);例如,如果您的應用程式回傳的 JSON 回應包含以下資料:
{
"user": {
"name": "Steve Schoger"
}
}您可以像這樣斷言 JSON 結構符合您的預期:
$response->assertJsonStructure([
'user' => [
'name',
]
]);有時,應用程式回傳的 JSON 回應可能包含物件陣列:
{
"user": [
{
"name": "Steve Schoger",
"age": 55,
"location": "Earth"
},
{
"name": "Mary Schoger",
"age": 60,
"location": "Earth"
}
]
}在這種情況下,您可以使用 * 字元來針對陣列中所有物件的結構進行斷言:
$response->assertJsonStructure([
'user' => [
'*' => [
'name',
'age',
'location'
]
]
]);assertJsonValidationErrors
斷言回應對於指定的鍵具有指定的 JSON 驗證錯誤。當針對驗證錯誤以 JSON 結構回傳而非快閃到 Session 的回應進行斷言時,應使用此方法:
$response->assertJsonValidationErrors(array $data, $responseKey = 'errors');📌 備註
更通用的 assertInvalid 方法可用於斷言回應具有以 JSON 回傳的驗證錯誤,或錯誤已快閃到 Session 儲存空間。
assertJsonValidationErrorFor
斷言回應對於指定的鍵具有任何 JSON 驗證錯誤:
$response->assertJsonValidationErrorFor(string $key, $responseKey = 'errors');assertMethodNotAllowed
斷言回應具有方法不允許 (405) 的 HTTP 狀態碼:
$response->assertMethodNotAllowed();assertMovedPermanently
斷言回應具有永久移至新位置 (301) 的 HTTP 狀態碼:
$response->assertMovedPermanently();assertLocation
斷言回應在 Location 標頭中具有指定的 URI 值:
$response->assertLocation($uri);assertContent
斷言指定的字串與回應內容符合:
$response->assertContent($value);assertNoContent
斷言回應具有指定的 HTTP 狀態碼且無內容:
$response->assertNoContent($status = 204);assertStreamed
斷言回應是一個串流回應:
$response->assertStreamed();assertStreamedContent
斷言指定的字串與串流回應內容符合:
$response->assertStreamedContent($value);assertNotFound
斷言回應具有未尋獲 (404) 的 HTTP 狀態碼:
$response->assertNotFound();assertOk
斷言回應具有 200 HTTP 狀態碼:
$response->assertOk();assertPaymentRequired
斷言回應具有需要付款 (402) 的 HTTP 狀態碼:
$response->assertPaymentRequired();assertPlainCookie
斷言回應包含指定的未加密 Cookie:
$response->assertPlainCookie($cookieName, $value = null);assertRedirect
斷言回應是重新導向至指定的 URI:
$response->assertRedirect($uri = null);assertRedirectBack
斷言回應是否正在重新導向回上一頁:
$response->assertRedirectBack();assertRedirectBackWithErrors
斷言回應是否正在重新導向回上一頁,且 Session 中包含指定的錯誤:
$response->assertRedirectBackWithErrors(
array $keys = [], $format = null, $errorBag = 'default'
);assertRedirectBackWithoutErrors
斷言回應是否正在重新導向回上一頁,且 Session 中不包含任何錯誤訊息:
$response->assertRedirectBackWithoutErrors();assertRedirectContains
斷言回應是否正在重新導向至包含指定字串的 URI:
$response->assertRedirectContains($string);assertRedirectToRoute
斷言回應是重新導向至指定的 具名路由:
$response->assertRedirectToRoute($name, $parameters = []);assertRedirectToSignedRoute
斷言回應是重新導向至指定的 簽章路由:
$response->assertRedirectToSignedRoute($name = null, $parameters = []);assertRequestTimeout
斷言回應具有請求超時 (408) 的 HTTP 狀態碼:
$response->assertRequestTimeout();assertSee
斷言回應中包含指定的字串。除非您將第二個引數傳遞為 false,否則此斷言會自動逸出指定的字串:
$response->assertSee($value, $escape = true);assertSeeInOrder
斷言回應中按順序包含指定的字串。除非您將第二個引數傳遞為 false,否則此斷言會自動逸出指定的字串:
$response->assertSeeInOrder(array $values, $escape = true);assertSeeText
斷言回應文字中包含指定的字串。除非您將第二個引數傳遞為 false,否則此斷言會自動逸出指定的字串。在進行斷言之前,回應內容會先被傳遞給 PHP 的 strip_tags 函式:
$response->assertSeeText($value, $escape = true);assertSeeTextInOrder
斷言回應文字中按順序包含指定的字串。除非您將第二個引數傳遞為 false,否則此斷言會自動逸出指定的字串。在進行斷言之前,回應內容會先被傳遞給 PHP 的 strip_tags 函式:
$response->assertSeeTextInOrder(array $values, $escape = true);assertServerError
斷言回應具有伺服器錯誤 (>= 500, < 600) 的 HTTP 狀態碼:
$response->assertServerError();assertServiceUnavailable
斷言回應具有「服務無法使用」(503) 的 HTTP 狀態碼:
$response->assertServiceUnavailable();assertSessionHas
斷言 Session 中包含指定的資料片段:
$response->assertSessionHas($key, $value = null);如果需要,可以將閉包作為第二個引數傳遞給 assertSessionHas 方法。如果閉包回傳 true,則斷言通過:
$response->assertSessionHas($key, function (User $value) {
return $value->name === 'Taylor Otwell';
});assertSessionHasInput
斷言 Session 在 快閃輸入陣列 中具有指定的值:
$response->assertSessionHasInput($key, $value = null);如果需要,可以將閉包作為第二個引數傳遞給 assertSessionHasInput 方法。如果閉包回傳 true,則斷言通過:
use Illuminate\Support\Facades\Crypt;
$response->assertSessionHasInput($key, function (string $value) {
return Crypt::decryptString($value) === 'secret';
});assertSessionHasAll
斷言 Session 包含指定的鍵值對陣列:
$response->assertSessionHasAll(array $data);例如,如果您的應用程式 Session 包含 name 與 status 鍵,您可以像這樣斷言兩者皆存在且具有指定的值:
$response->assertSessionHasAll([
'name' => 'Taylor Otwell',
'status' => 'active',
]);assertSessionHasErrors
斷言 Session 包含指定 $keys 的錯誤。如果 $keys 是一個關聯陣列,則斷言 Session 中每個欄位 (鍵) 都包含特定的錯誤訊息 (值)。當測試將驗證錯誤快閃到 Session 而非以 JSON 結構回傳的路由時,應使用此方法:
$response->assertSessionHasErrors(
array $keys = [], $format = null, $errorBag = 'default'
);例如,要斷言 name 與 email 欄位具有已快閃到 Session 的驗證錯誤訊息,您可以像這樣呼叫 assertSessionHasErrors 方法:
$response->assertSessionHasErrors(['name', 'email']);或者,您可以斷言指定的欄位具有特定的驗證錯誤訊息:
$response->assertSessionHasErrors([
'name' => 'The given name was invalid.'
]);📌 備註
更通用的 assertInvalid 方法可用於斷言回應具有以 JSON 回傳的驗證錯誤,或錯誤已快閃到 Session 儲存空間。
assertSessionHasErrorsIn
斷言 Session 在指定的 錯誤袋 (error bag) 中包含指定 $keys 的錯誤。如果 $keys 是一個關聯陣列,則斷言 Session 的該錯誤袋中每個欄位 (鍵) 都包含特定的錯誤訊息 (值):
$response->assertSessionHasErrorsIn($errorBag, $keys = [], $format = null);assertSessionHasNoErrors
斷言 Session 沒有驗證錯誤:
$response->assertSessionHasNoErrors();assertSessionDoesntHaveErrors
斷言 Session 對於指定的鍵沒有驗證錯誤:
$response->assertSessionDoesntHaveErrors($keys = [], $format = null, $errorBag = 'default');📌 備註
更通用的 assertValid 方法可用於斷言回應沒有以 JSON 回傳的驗證錯誤,且沒有將錯誤快閃到 Session 儲存空間。
assertSessionMissing
斷言 Session 不包含指定的鍵:
$response->assertSessionMissing($key);assertSessionMissingInput
斷言 Session 的快閃輸入陣列中缺少指定的輸入鍵:
$response->assertSessionMissingInput($key);assertStatus
斷言回應具有指定的 HTTP 狀態碼:
$response->assertStatus($code);assertSuccessful
斷言回應具有成功 (>= 200 且 < 300) 的 HTTP 狀態碼:
$response->assertSuccessful();assertTooManyRequests
斷言回應具有太多請求 (429) 的 HTTP 狀態碼:
$response->assertTooManyRequests();assertUnauthorized
斷言回應具有未授權 (401) 的 HTTP 狀態碼:
$response->assertUnauthorized();assertUnprocessable
斷言回應具有無法處理的實體 (422) 的 HTTP 狀態碼:
$response->assertUnprocessable();assertUnsupportedMediaType
斷言回應具有不支援的媒體類型 (415) 的 HTTP 狀態碼:
$response->assertUnsupportedMediaType();assertValid
斷言回應對於指定的鍵沒有驗證錯誤。此方法可用於針對以 JSON 結構回傳驗證錯誤的回應,或驗證錯誤已快閃到 Session 的回應進行斷言:
// Assert that no validation errors are present...
$response->assertValid();
// Assert that the given keys do not have validation errors...
$response->assertValid(['name', 'email']);assertInvalid
斷言回應對於指定的鍵具有驗證錯誤。此方法可用於針對以 JSON 結構回傳驗證錯誤的回應,或驗證錯誤已快閃到 Session 的回應進行斷言:
$response->assertInvalid(['name', 'email']);您也可以斷言指定的鍵具有特定的驗證錯誤訊息。在執行此操作時,您可以提供完整訊息或僅提供訊息的一小部分:
$response->assertInvalid([
'name' => 'The name field is required.',
'email' => 'valid email address',
]);如果您想斷言指定的欄位是「唯一」具有驗證錯誤的欄位,可以使用 assertOnlyInvalid 方法:
$response->assertOnlyInvalid(['name', 'email']);assertViewHas
斷言回應視圖包含指定的資料片段:
$response->assertViewHas($key, $value = null);將閉包作為第二個引數傳遞給 assertViewHas 方法,可讓您檢查並針對特定的視圖資料進行斷言:
$response->assertViewHas('user', function (User $user) {
return $user->name === 'Taylor';
});此外,視圖資料可以作為回應上的陣列變數來存取,讓您方便地檢查它:
expect($response['name'])->toBe('Taylor');$this->assertEquals('Taylor', $response['name']);assertViewHasAll
斷言回應視圖具有指定的資料列表:
$response->assertViewHasAll(array $data);此方法可用於斷言視圖僅包含符合指定鍵的資料:
$response->assertViewHasAll([
'name',
'email',
]);或者,您可以斷言視圖資料存在且具有特定值:
$response->assertViewHasAll([
'name' => 'Taylor Otwell',
'email' => '[email protected],',
]);assertViewIs
斷言路由回傳了指定的視圖:
$response->assertViewIs($value);assertViewMissing
斷言指定的資料鍵未提供給應用程式回應中回傳的視圖:
$response->assertViewMissing($key);認證斷言
Laravel 也提供了各種與認證相關的斷言,讓您可以在應用程式的功能測試中使用。請注意,這些方法是在測試類別本身呼叫的,而不是由 get 和 post 等方法回傳的 Illuminate\Testing\TestResponse 實例。
assertAuthenticated
斷言使用者已通過認證:
$this->assertAuthenticated($guard = null);assertGuest
斷言使用者未通過認證:
$this->assertGuest($guard = null);assertAuthenticatedAs
斷言特定的使用者已通過認證:
$this->assertAuthenticatedAs($user, $guard = null);驗證斷言
Laravel 提供了兩個主要的驗證相關斷言,您可以使用它們來確保請求中提供的資料是有效的或是無效的。
assertValid
斷言回應中給定的鍵 (Keys) 沒有驗證錯誤。此方法可用於斷言以 JSON 結構回傳驗證錯誤的回應,或是驗證錯誤已被存入 Session 的回應:
// Assert that no validation errors are present...
$response->assertValid();
// Assert that the given keys do not have validation errors...
$response->assertValid(['name', 'email']);assertInvalid
斷言回應中給定的鍵具有驗證錯誤。此方法可用於斷言以 JSON 結構回傳驗證錯誤的回應,或是驗證錯誤已被存入 Session 的回應:
$response->assertInvalid(['name', 'email']);您也可以斷言給定的鍵具有特定的驗證錯誤訊息。執行此操作時,您可以提供完整的訊息或僅提供訊息的一小部分:
$response->assertInvalid([
'name' => 'The name field is required.',
'email' => 'valid email address',
]);