HTTP 测试
简介
Laravel 提供了一个非常流畅的 API,用于向你的应用程序发起 HTTP 请求并检查响应。例如,请看下面定义的特性测试:
1<?php2 3test('the application returns a successful response', function () {4 $response = $this->get('/');5 6 $response->assertStatus(200);7});
1<?php 2 3namespace Tests\Feature; 4 5use Tests\TestCase; 6 7class ExampleTest extends TestCase 8{ 9 /**10 * A basic test example.11 */12 public function test_the_application_returns_a_successful_response(): void13 {14 $response = $this->get('/');15 16 $response->assertStatus(200);17 }18}
get 方法向应用程序发起 GET 请求,而 assertStatus 方法断言返回的响应应具有给定的 HTTP 状态码。除了这个简单的断言外,Laravel 还包含各种用于检查响应头、内容、JSON 结构等的断言。
发起请求
要向你的应用程序发起请求,你可以在测试中使用 get、post、put、patch 或 delete 方法。这些方法实际上并不会向你的应用程序发起“真实”的 HTTP 请求。相反,整个网络请求是在内部模拟的。
测试请求方法返回的不是 Illuminate\Http\Response 实例,而是 Illuminate\Testing\TestResponse 实例,它提供了各种有用的断言,允许你检查应用程序的响应。
1<?php2 3test('basic request', function () {4 $response = $this->get('/');5 6 $response->assertStatus(200);7});
1<?php 2 3namespace Tests\Feature; 4 5use Tests\TestCase; 6 7class ExampleTest extends TestCase 8{ 9 /**10 * A basic test example.11 */12 public function test_a_basic_request(): void13 {14 $response = $this->get('/');15 16 $response->assertStatus(200);17 }18}
通常情况下,你的每个测试都应该只向应用程序发起一次请求。如果在单个测试方法中执行多次请求,可能会出现意外行为。
为方便起见,运行测试时 CSRF 中间件会自动禁用。
自定义请求头
你可以使用 withHeaders 方法在请求发送到应用程序之前自定义请求头。此方法允许你为请求添加任何你想要的自定义请求头。
1<?php2 3test('interacting with headers', function () {4 $response = $this->withHeaders([5 'X-Header' => 'Value',6 ])->post('/user', ['name' => 'Sally']);7 8 $response->assertStatus(201);9});
1<?php 2 3namespace Tests\Feature; 4 5use Tests\TestCase; 6 7class ExampleTest extends TestCase 8{ 9 /**10 * A basic functional test example.11 */12 public function test_interacting_with_headers(): void13 {14 $response = $this->withHeaders([15 'X-Header' => 'Value',16 ])->post('/user', ['name' => 'Sally']);17 18 $response->assertStatus(201);19 }20}
Cookies
你可以使用 withCookie 或 withCookies 方法在发起请求之前设置 cookie 值。withCookie 方法接受 cookie 名称和值作为两个参数,而 withCookies 方法接受名称/值对数组。
1<?php 2 3test('interacting with cookies', function () { 4 $response = $this->withCookie('color', 'blue')->get('/'); 5 6 $response = $this->withCookies([ 7 'color' => 'blue', 8 'name' => 'Taylor', 9 ])->get('/');10 11 //12});
1<?php 2 3namespace Tests\Feature; 4 5use Tests\TestCase; 6 7class ExampleTest extends TestCase 8{ 9 public function test_interacting_with_cookies(): void10 {11 $response = $this->withCookie('color', 'blue')->get('/');12 13 $response = $this->withCookies([14 'color' => 'blue',15 'name' => 'Taylor',16 ])->get('/');17 18 //19 }20}
会话 / 身份验证
Laravel 提供了几个在 HTTP 测试期间与会话交互的辅助方法。首先,你可以使用 withSession 方法将会话数据设置为给定的数组。这在向应用程序发起请求之前加载会话数据非常有用。
1<?php2 3test('interacting with the session', function () {4 $response = $this->withSession(['banned' => false])->get('/');5 6 //7});
1<?php 2 3namespace Tests\Feature; 4 5use Tests\TestCase; 6 7class ExampleTest extends TestCase 8{ 9 public function test_interacting_with_the_session(): void10 {11 $response = $this->withSession(['banned' => false])->get('/');12 13 //14 }15}
Laravel 的会话通常用于为当前经过身份验证的用户维护状态。因此,actingAs 辅助方法提供了一种简单的方法来将给定用户验证为当前用户。例如,我们可以使用模型工厂来生成并验证用户。
1<?php 2 3use App\Models\User; 4 5test('an action that requires authentication', function () { 6 $user = User::factory()->create(); 7 8 $response = $this->actingAs($user) 9 ->withSession(['banned' => false])10 ->get('/');11 12 //13});
1<?php 2 3namespace Tests\Feature; 4 5use App\Models\User; 6use Tests\TestCase; 7 8class ExampleTest extends TestCase 9{10 public function test_an_action_that_requires_authentication(): void11 {12 $user = User::factory()->create();13 14 $response = $this->actingAs($user)15 ->withSession(['banned' => false])16 ->get('/');17 18 //19 }20}
你还可以通过将守卫(guard)名称作为第二个参数传递给 actingAs 方法,来指定应该使用哪个守卫来验证给定用户。提供给 actingAs 方法的守卫也将成为测试期间的默认守卫。
1$this->actingAs($user, 'web');
如果你想确保请求处于未验证状态,可以使用 actingAsGuest 方法。
1$this->actingAsGuest();
调试响应
在向应用程序发起测试请求后,可以使用 dump、dumpHeaders 和 dumpSession 方法来检查和调试响应内容。
1<?php2 3test('basic test', function () {4 $response = $this->get('/');5 6 $response->dump();7 $response->dumpHeaders();8 $response->dumpSession();9});
1<?php 2 3namespace Tests\Feature; 4 5use Tests\TestCase; 6 7class ExampleTest extends TestCase 8{ 9 /**10 * A basic test example.11 */12 public function test_basic_test(): void13 {14 $response = $this->get('/');15 16 $response->dump();17 $response->dumpHeaders();18 $response->dumpSession();19 }20}
或者,你可以使用 dd、ddHeaders、ddBody、ddJson 和 ddSession 方法来转储有关响应的信息,然后停止执行。
1<?php 2 3test('basic test', function () { 4 $response = $this->get('/'); 5 6 $response->dd(); 7 $response->ddHeaders(); 8 $response->ddBody(); 9 $response->ddJson();10 $response->ddSession();11});
1<?php 2 3namespace Tests\Feature; 4 5use Tests\TestCase; 6 7class ExampleTest extends TestCase 8{ 9 /**10 * A basic test example.11 */12 public function test_basic_test(): void13 {14 $response = $this->get('/');15 16 $response->dd();17 $response->ddHeaders();18 $response->ddBody();19 $response->ddJson();20 $response->ddSession();21 }22}
异常处理
有时你可能需要测试应用程序是否抛出了特定异常。为此,你可以通过 Exceptions 门面(facade)来“伪造”异常处理程序。一旦伪造了异常处理程序,你就可以利用 assertReported 和 assertNotReported 方法对请求期间抛出的异常进行断言。
1<?php 2 3use App\Exceptions\InvalidOrderException; 4use Illuminate\Support\Facades\Exceptions; 5 6test('exception is thrown', function () { 7 Exceptions::fake(); 8 9 $response = $this->get('/order/1');10 11 // Assert an exception was thrown...12 Exceptions::assertReported(InvalidOrderException::class);13 14 // Assert against the exception...15 Exceptions::assertReported(function (InvalidOrderException $e) {16 return $e->getMessage() === 'The order was invalid.';17 });18});
1<?php 2 3namespace Tests\Feature; 4 5use App\Exceptions\InvalidOrderException; 6use Illuminate\Support\Facades\Exceptions; 7use Tests\TestCase; 8 9class ExampleTest extends TestCase10{11 /**12 * A basic test example.13 */14 public function test_exception_is_thrown(): void15 {16 Exceptions::fake();17 18 $response = $this->get('/');19 20 // Assert an exception was thrown...21 Exceptions::assertReported(InvalidOrderException::class);22 23 // Assert against the exception...24 Exceptions::assertReported(function (InvalidOrderException $e) {25 return $e->getMessage() === 'The order was invalid.';26 });27 }28}
assertNotReported 和 assertNothingReported 方法可用于断言请求期间未抛出给定异常,或未抛出任何异常。
1Exceptions::assertNotReported(InvalidOrderException::class);2 3Exceptions::assertNothingReported();
你可以在发起请求之前调用 withoutExceptionHandling 方法,彻底禁用给定请求的异常处理。
1$response = $this->withoutExceptionHandling()->get('/');
此外,如果你想确保你的应用程序没有使用 PHP 语言或应用程序所依赖的库已弃用的功能,你可以在发起请求之前调用 withoutDeprecationHandling 方法。当禁用弃用处理时,弃用警告将被转换为异常,从而导致测试失败。
1$response = $this->withoutDeprecationHandling()->get('/');
assertThrows 方法可用于断言给定闭包内的代码抛出了指定类型的异常。
1$this->assertThrows(2 fn () => (new ProcessOrder)->execute(),3 OrderInvalid::class4);
如果你想检查抛出的异常并对其进行断言,可以将一个闭包作为 assertThrows 方法的第二个参数传入。
1$this->assertThrows(2 fn () => (new ProcessOrder)->execute(),3 fn (OrderInvalid $e) => $e->orderId() === 123;4);
assertDoesntThrow 方法可用于断言给定闭包内的代码不会抛出任何异常。
1$this->assertDoesntThrow(fn () => (new ProcessOrder)->execute());
测试 JSON API
Laravel 还提供了几个用于测试 JSON API 及其响应的辅助方法。例如,json、getJson、postJson、putJson、patchJson、deleteJson 和 optionsJson 方法可用于使用各种 HTTP 谓词发起 JSON 请求。你还可以轻松地将数据和请求头传递给这些方法。首先,让我们编写一个测试,向 /api/user 发起 POST 请求,并断言返回了预期的 JSON 数据。
1<?php 2 3test('making an api request', function () { 4 $response = $this->postJson('/api/user', ['name' => 'Sally']); 5 6 $response 7 ->assertStatus(201) 8 ->assertJson([ 9 'created' => true,10 ]);11});
1<?php 2 3namespace Tests\Feature; 4 5use Tests\TestCase; 6 7class ExampleTest extends TestCase 8{ 9 /**10 * A basic functional test example.11 */12 public function test_making_an_api_request(): void13 {14 $response = $this->postJson('/api/user', ['name' => 'Sally']);15 16 $response17 ->assertStatus(201)18 ->assertJson([19 'created' => true,20 ]);21 }22}
此外,JSON 响应数据可以作为响应对象上的数组变量进行访问,这使你能够方便地检查 JSON 响应中返回的各个值。
1expect($response['created'])->toBeTrue();
1$this->assertTrue($response['created']);
assertJson 方法将响应转换为数组,以验证给定数组是否存在于应用程序返回的 JSON 响应中。因此,如果 JSON 响应中还有其他属性,只要存在给定的片段,此测试仍然会通过。
断言精确的 JSON 匹配
如前所述,assertJson 方法可用于断言 JSON 片段存在于 JSON 响应中。如果你想验证给定数组是否完全匹配应用程序返回的 JSON,你应该使用 assertExactJson 方法。
1<?php 2 3test('asserting an exact json match', function () { 4 $response = $this->postJson('/user', ['name' => 'Sally']); 5 6 $response 7 ->assertStatus(201) 8 ->assertExactJson([ 9 'created' => true,10 ]);11});
1<?php 2 3namespace Tests\Feature; 4 5use Tests\TestCase; 6 7class ExampleTest extends TestCase 8{ 9 /**10 * A basic functional test example.11 */12 public function test_asserting_an_exact_json_match(): void13 {14 $response = $this->postJson('/user', ['name' => 'Sally']);15 16 $response17 ->assertStatus(201)18 ->assertExactJson([19 'created' => true,20 ]);21 }22}
在 JSON 路径上进行断言
如果你想验证 JSON 响应在指定路径是否包含给定的数据,你应该使用 assertJsonPath 方法。
1<?php2 3test('asserting a json path value', function () {4 $response = $this->postJson('/user', ['name' => 'Sally']);5 6 $response7 ->assertStatus(201)8 ->assertJsonPath('team.owner.name', 'Darian');9});
1<?php 2 3namespace Tests\Feature; 4 5use Tests\TestCase; 6 7class ExampleTest extends TestCase 8{ 9 /**10 * A basic functional test example.11 */12 public function test_asserting_a_json_paths_value(): void13 {14 $response = $this->postJson('/user', ['name' => 'Sally']);15 16 $response17 ->assertStatus(201)18 ->assertJsonPath('team.owner.name', 'Darian');19 }20}
assertJsonPath 方法也接受一个闭包,该闭包可用于动态判断断言是否应该通过。
1$response->assertJsonPath('team.owner.name', fn (string $name) => strlen($name) >= 3);
流式 JSON 测试
Laravel 还提供了一种优美的方式来流式测试应用程序的 JSON 响应。首先,将一个闭包传递给 assertJson 方法。此闭包将被调用,并接收一个 Illuminate\Testing\Fluent\AssertableJson 实例,该实例可用于对应用程序返回的 JSON 进行断言。where 方法可用于对 JSON 的特定属性进行断言,而 missing 方法可用于断言 JSON 中缺少特定属性。
1use Illuminate\Testing\Fluent\AssertableJson; 2 3test('fluent json', function () { 4 $response = $this->getJson('/users/1'); 5 6 $response 7 ->assertJson(fn (AssertableJson $json) => 8 $json->where('id', 1) 9 ->where('name', 'Victoria Faith')11 ->whereNot('status', 'pending')12 ->missing('password')13 ->etc()14 );15});
1use Illuminate\Testing\Fluent\AssertableJson; 2 3/** 4 * A basic functional test example. 5 */ 6public function test_fluent_json(): void 7{ 8 $response = $this->getJson('/users/1'); 9 10 $response11 ->assertJson(fn (AssertableJson $json) =>12 $json->where('id', 1)13 ->where('name', 'Victoria Faith')15 ->whereNot('status', 'pending')16 ->missing('password')17 ->etc()18 );19}
理解 etc 方法
在上面的示例中,你可能注意到我们在断言链的末尾调用了 etc 方法。此方法通知 Laravel JSON 对象中可能还存在其他属性。如果未使用 etc 方法,且 JSON 对象中存在你未进行断言的其他属性,测试将会失败。
这种行为背后的意图是通过强制你明确地对属性进行断言,或者通过 etc 方法显式允许附加属性,来保护你不无意中泄露 JSON 响应中的敏感信息。
但是,你应该意识到,在断言链中不包含 etc 方法并不能确保 JSON 对象中嵌套的数组内没有添加额外的属性。etc 方法仅确保在调用 etc 方法的嵌套级别不存在额外的属性。
断言属性的存在/缺失
要断言属性存在或缺失,可以使用 has 和 missing 方法。
1$response->assertJson(fn (AssertableJson $json) =>2 $json->has('data')3 ->missing('message')4);
此外,hasAll 和 missingAll 方法允许同时断言多个属性的存在或缺失。
1$response->assertJson(fn (AssertableJson $json) =>2 $json->hasAll(['status', 'data'])3 ->missingAll(['message', 'code'])4);
你可以使用 hasAny 方法来确定给定属性列表中至少有一个属性是否存在。
1$response->assertJson(fn (AssertableJson $json) =>2 $json->has('status')3 ->hasAny('data', 'message', 'code')4);
针对 JSON 集合进行断言
通常,你的路由会返回包含多个条目的 JSON 响应,例如多个用户。
1Route::get('/users', function () {2 return User::all();3});
在这种情况下,我们可以使用流式 JSON 对象的 has 方法来对响应中包含的用户进行断言。例如,我们断言 JSON 响应包含三个用户。接下来,我们将使用 first 方法对集合中的第一个用户进行一些断言。first 方法接受一个闭包,该闭包接收另一个可断言的 JSON 字符串,我们可以使用它对 JSON 集合中的第一个对象进行断言。
1$response 2 ->assertJson(fn (AssertableJson $json) => 3 $json->has(3) 4 ->first(fn (AssertableJson $json) => 5 $json->where('id', 1) 6 ->where('name', 'Victoria Faith') 8 ->missing('password') 9 ->etc()10 )11 );
如果你想对 JSON 集合中的每一项进行相同的断言,可以使用 each 方法。
1$response 2 ->assertJson(fn (AssertableJson $json) => 3 $json->has(3) 4 ->each(fn (AssertableJson $json) => 5 $json->whereType('id', 'integer') 6 ->whereType('name', 'string') 7 ->whereType('email', 'string') 8 ->missing('password') 9 ->etc()10 )11 );
限定 JSON 集合断言的作用域
有时,应用程序的路由会返回分配了命名键的 JSON 集合。
1Route::get('/users', function () {2 return [3 'meta' => [...],4 'users' => User::all(),5 ];6})
测试这些路由时,可以使用 has 方法来断言集合中条目的数量。此外,还可以使用 has 方法来限定断言链的作用域。
1$response 2 ->assertJson(fn (AssertableJson $json) => 3 $json->has('meta') 4 ->has('users', 3) 5 ->has('users.0', fn (AssertableJson $json) => 6 $json->where('id', 1) 7 ->where('name', 'Victoria Faith') 9 ->missing('password')10 ->etc()11 )12 );
但是,无需两次调用 has 方法来对 users 集合进行断言,你可以只调用一次,并将闭包作为其第三个参数。执行此操作时,闭包将被自动调用,并限定在集合的第一项中。
1$response 2 ->assertJson(fn (AssertableJson $json) => 3 $json->has('meta') 4 ->has('users', 3, fn (AssertableJson $json) => 5 $json->where('id', 1) 6 ->where('name', 'Victoria Faith') 8 ->missing('password') 9 ->etc()10 )11 );
断言 JSON 类型
你可能只想断言 JSON 响应中的属性属于某种特定类型。Illuminate\Testing\Fluent\AssertableJson 类提供了 whereType 和 whereAllType 方法来做到这一点。
1$response->assertJson(fn (AssertableJson $json) =>2 $json->whereType('id', 'integer')3 ->whereAllType([4 'users.0.name' => 'string',5 'meta' => 'array'6 ])7);
你可以使用 | 字符指定多种类型,或者将类型数组作为 whereType 方法的第二个参数传递。如果响应值是列出的任何类型,则断言成功。
1$response->assertJson(fn (AssertableJson $json) =>2 $json->whereType('name', 'string|null')3 ->whereType('id', ['string', 'integer'])4);
whereType 和 whereAllType 方法可识别以下类型:string、integer、double、boolean、array 和 null。
测试文件上传
Illuminate\Http\UploadedFile 类提供了一个 fake 方法,可用于生成用于测试的虚拟文件或图像。这与 Storage 门面的 fake 方法结合使用,极大地简化了文件上传的测试。例如,你可以结合这两个特性来轻松测试头像上传表单。
1<?php 2 3use Illuminate\Http\UploadedFile; 4use Illuminate\Support\Facades\Storage; 5 6test('avatars can be uploaded', function () { 7 Storage::fake('avatars'); 8 9 $file = UploadedFile::fake()->image('avatar.jpg');10 11 $response = $this->post('/avatar', [12 'avatar' => $file,13 ]);14 15 Storage::disk('avatars')->assertExists($file->hashName());16});
1<?php 2 3namespace Tests\Feature; 4 5use Illuminate\Http\UploadedFile; 6use Illuminate\Support\Facades\Storage; 7use Tests\TestCase; 8 9class ExampleTest extends TestCase10{11 public function test_avatars_can_be_uploaded(): void12 {13 Storage::fake('avatars');14 15 $file = UploadedFile::fake()->image('avatar.jpg');16 17 $response = $this->post('/avatar', [18 'avatar' => $file,19 ]);20 21 Storage::disk('avatars')->assertExists($file->hashName());22 }23}
如果你想断言给定文件不存在,可以使用 Storage 门面提供的 assertMissing 方法。
1Storage::fake('avatars');2 3// ...4 5Storage::disk('avatars')->assertMissing('missing.jpg');
伪造文件自定义
当使用 UploadedFile 类提供的 fake 方法创建文件时,你可以指定图像的宽度、高度和大小(以千字节为单位),以便更好地测试应用程序的验证规则。
1UploadedFile::fake()->image('avatar.jpg', $width, $height)->size(100);
除了创建图像外,你还可以使用 create 方法创建任何其他类型的文件。
1UploadedFile::fake()->create('document.pdf', $sizeInKilobytes);
如果需要,你可以将 $mimeType 参数传递给该方法,以明确定义文件应返回的 MIME 类型。
1UploadedFile::fake()->create(2 'document.pdf', $sizeInKilobytes, 'application/pdf'3);
测试视图
Laravel 还允许你在不向应用程序发起模拟 HTTP 请求的情况下渲染视图。为此,你可以在测试中调用 view 方法。view 方法接受视图名称和可选的数据数组。该方法返回一个 Illuminate\Testing\TestView 实例,它提供了多种方法来方便地对视图内容进行断言。
1<?php2 3test('a welcome view can be rendered', function () {4 $view = $this->view('welcome', ['name' => 'Taylor']);5 6 $view->assertSee('Taylor');7});
1<?php 2 3namespace Tests\Feature; 4 5use Tests\TestCase; 6 7class ExampleTest extends TestCase 8{ 9 public function test_a_welcome_view_can_be_rendered(): void10 {11 $view = $this->view('welcome', ['name' => 'Taylor']);12 13 $view->assertSee('Taylor');14 }15}
TestView 类提供以下断言方法:assertSee、assertSeeInOrder、assertSeeText、assertSeeTextInOrder、assertDontSee 和 assertDontSeeText。
如果需要,你可以通过将 TestView 实例转换为字符串来获取原始的、已渲染的视图内容。
1$contents = (string) $this->view('welcome');
共享错误
某些视图可能依赖于Laravel 提供的全局错误包中共享的错误。要使用错误消息填充错误包,可以使用 withViewErrors 方法。
1$view = $this->withViewErrors([2 'name' => ['Please provide a valid name.']3])->view('form');4 5$view->assertSee('Please provide a valid name.');
渲染 Blade 与组件
如有必要,你可以使用 blade 方法来计算并渲染原始的 Blade 字符串。与 view 方法一样,blade 方法返回一个 Illuminate\Testing\TestView 实例。
1$view = $this->blade(2 '<x-component :name="$name" />',3 ['name' => 'Taylor']4);5 6$view->assertSee('Taylor');
你可以使用 component 方法来计算并渲染 Blade 组件。component 方法返回一个 Illuminate\Testing\TestComponent 实例。
1$view = $this->component(Profile::class, ['name' => 'Taylor']);2 3$view->assertSee('Taylor');
缓存路由
在测试运行之前,Laravel 会启动一个新的应用程序实例,包括收集所有定义的路由。如果你的应用程序有很多路由文件,你可能希望在测试用例中添加 Illuminate\Foundation\Testing\WithCachedRoutes trait。在使用此 trait 的测试中,路由会被构建一次并存储在内存中,这意味着路由收集过程在整个测试套件中只会运行一次。
1<?php 2 3use App\Http\Controllers\UserController; 4use Illuminate\Foundation\Testing\WithCachedRoutes; 5 6pest()->use(WithCachedRoutes::class); 7 8test('basic example', function () { 9 $this->get(action([UserController::class, 'index']));10 11 // ...12});
1<?php 2 3namespace Tests\Feature; 4 5use App\Http\Controllers\UserController; 6use Illuminate\Foundation\Testing\WithCachedRoutes; 7use Tests\TestCase; 8 9class BasicTest extends TestCase10{11 use WithCachedRoutes;12 13 /**14 * A basic functional test example.15 */16 public function test_basic_example(): void17 {18 $response = $this->get(action([UserController::class, 'index']));19 20 // ...21 }22}
可用断言
响应断言
Laravel 的 Illuminate\Testing\TestResponse 类提供了多种自定义断言方法,你可以在测试应用程序时使用。这些断言可以在 json、get、post、put 和 delete 测试方法返回的响应上访问。
assertAccepted assertBadRequest assertClientError assertConflict assertCookie assertCookieExpired assertCookieNotExpired assertCookieMissing assertCreated assertDontSee assertDontSeeText assertDownload assertExactJson assertExactJsonStructure assertForbidden assertFound assertGone assertHeader assertHeaderContains assertHeaderMissing assertInternalServerError assertJson assertJsonCount assertJsonFragment assertJsonIsArray assertJsonIsObject assertJsonMissing assertJsonMissingExact assertJsonMissingValidationErrors assertJsonPath assertJsonMissingPath assertJsonStructure assertJsonValidationErrors assertJsonValidationErrorFor assertLocation assertMethodNotAllowed assertMovedPermanently assertContent assertNoContent assertStreamed assertStreamedContent assertNotFound assertOk assertPaymentRequired assertPlainCookie assertRedirect assertRedirectBack assertRedirectBackWithErrors assertRedirectBackWithoutErrors assertRedirectContains assertRedirectToRoute assertRedirectToSignedRoute assertRequestTimeout assertSee assertSeeInOrder assertSeeText assertSeeTextInOrder assertServerError assertServiceUnavailable assertSessionHas assertSessionHasInput assertSessionHasAll assertSessionHasErrors assertSessionHasErrorsIn assertSessionHasNoErrors assertSessionDoesntHaveErrors assertSessionMissing assertStatus assertSuccessful assertTooManyRequests assertUnauthorized assertUnprocessable assertUnsupportedMediaType assertValid assertInvalid assertViewHas assertViewHasAll assertViewIs assertViewMissing
assertAccepted
断言响应具有已接受 (202) HTTP 状态码
1$response->assertAccepted();
assertBadRequest
断言响应具有错误请求 (400) HTTP 状态码
1$response->assertBadRequest();
assertClientError
断言响应具有客户端错误 (>= 400, < 500) HTTP 状态码
1$response->assertClientError();
assertConflict
断言响应具有冲突 (409) HTTP 状态码
1$response->assertConflict();
assertCookie
断言响应包含给定的 cookie
1$response->assertCookie($cookieName, $value = null);
assertCookieExpired
断言响应包含给定的 cookie 且该 cookie 已过期
1$response->assertCookieExpired($cookieName);
assertCookieNotExpired
断言响应包含给定的 cookie 且该 cookie 未过期
1$response->assertCookieNotExpired($cookieName);
assertCookieMissing
断言响应不包含给定的 cookie
1$response->assertCookieMissing($cookieName);
assertCreated
断言响应具有 201 HTTP 状态码
1$response->assertCreated();
assertDontSee
断言给定的字符串不包含在应用程序返回的响应中。此断言将自动转义给定的字符串,除非你传入 false 作为第二个参数
1$response->assertDontSee($value, $escape = true);
assertDontSeeText
断言给定的字符串不包含在响应文本中。此断言将自动转义给定的字符串,除非你传入 false 作为第二个参数。此方法在进行断言之前会将响应内容传递给 PHP 的 strip_tags 函数
1$response->assertDontSeeText($value, $escape = true);
assertDownload
断言响应为“下载”。通常,这意味着返回响应的被调用路由返回了 Response::download 响应、BinaryFileResponse 或 Storage::download 响应
1$response->assertDownload();
如果你愿意,你可以断言可下载文件被分配了给定的文件名
1$response->assertDownload('image.jpg');
assertExactJson
断言响应包含给定的 JSON 数据的精确匹配
1$response->assertExactJson(array $data);
assertExactJsonStructure
断言响应包含给定的 JSON 结构的精确匹配
1$response->assertExactJsonStructure(array $data);
此方法是 assertJsonStructure 的一个更严格的变体。与 assertJsonStructure 不同,如果响应包含任何未显式包含在预期 JSON 结构中的键,此方法将会失败。
assertForbidden
断言响应具有禁止访问 (403) HTTP 状态码
1$response->assertForbidden();
assertFound
断言响应具有已找到 (302) HTTP 状态码
1$response->assertFound();
assertGone
断言响应具有已删除 (410) HTTP 状态码
1$response->assertGone();
assertHeader
断言响应上存在给定的头和值
1$response->assertHeader($headerName, $value = null);
assertHeaderContains
断言给定的头包含给定的子字符串值
1$response->assertHeaderContains($headerName, $value);
assertHeaderMissing
断言响应上不存在给定的头
1$response->assertHeaderMissing($headerName);
assertInternalServerError
断言响应具有“内部服务器错误” (500) HTTP 状态码
1$response->assertInternalServerError();
assertJson
断言响应包含给定的 JSON 数据
1$response->assertJson(array $data, $strict = false);
assertJson 方法将响应转换为数组,以验证给定数组是否存在于应用程序返回的 JSON 响应中。因此,如果 JSON 响应中还有其他属性,只要存在给定的片段,此测试仍然会通过。
assertJsonCount
断言响应 JSON 在给定键处有一个包含预期数量条目的数组
1$response->assertJsonCount($count, $key = null);
assertJsonFragment
断言响应在响应的任何位置包含给定的 JSON 数据
1Route::get('/users', function () { 2 return [ 3 'users' => [ 4 [ 5 'name' => 'Taylor Otwell', 6 ], 7 ], 8 ]; 9});10 11$response->assertJsonFragment(['name' => 'Taylor Otwell']);
assertJsonIsArray
断言响应 JSON 是一个数组
1$response->assertJsonIsArray();
assertJsonIsObject
断言响应 JSON 是一个对象
1$response->assertJsonIsObject();
assertJsonMissing
断言响应不包含给定的 JSON 数据
1$response->assertJsonMissing(array $data);
assertJsonMissingExact
断言响应不包含精确的 JSON 数据
1$response->assertJsonMissingExact(array $data);
assertJsonMissingValidationErrors
断言响应对于给定键没有 JSON 验证错误
1$response->assertJsonMissingValidationErrors($keys);
更通用的 assertValid 方法可用于断言响应没有作为 JSON 返回的验证错误,并且没有错误闪存到会话存储中。
assertJsonPath
断言响应在指定路径包含给定的数据
1$response->assertJsonPath($path, $expectedValue);
例如,如果你的应用程序返回以下 JSON 响应
1{2 "user": {3 "name": "Steve Schoger"4 }5}
你可以像这样断言 user 对象的 name 属性与给定值匹配
1$response->assertJsonPath('user.name', 'Steve Schoger');
assertJsonMissingPath
断言响应不包含给定的路径
1$response->assertJsonMissingPath($path);
例如,如果你的应用程序返回以下 JSON 响应
1{2 "user": {3 "name": "Steve Schoger"4 }5}
你可以断言它不包含 user 对象的 email 属性
1$response->assertJsonMissingPath('user.email');
assertJsonStructure
断言响应具有给定的 JSON 结构
1$response->assertJsonStructure(array $structure);
例如,如果你的应用程序返回的 JSON 响应包含以下数据
1{2 "user": {3 "name": "Steve Schoger"4 }5}
你可以像这样断言 JSON 结构符合你的预期
1$response->assertJsonStructure([2 'user' => [3 'name',4 ]5]);
有时,你的应用程序返回的 JSON 响应可能包含对象数组
1{ 2 "user": [ 3 { 4 "name": "Steve Schoger", 5 "age": 55, 6 "location": "Earth" 7 }, 8 { 9 "name": "Mary Schoger",10 "age": 60,11 "location": "Earth"12 }13 ]14}
在这种情况下,你可以使用 * 字符来对数组中所有对象的结构进行断言
1$response->assertJsonStructure([2 'user' => [3 '*' => [4 'name',5 'age',6 'location'7 ]8 ]9]);
assertJsonValidationErrors
断言响应对于给定键具有给定的 JSON 验证错误。此方法应在断言验证错误作为 JSON 结构返回而不是闪存到会话的响应时使用
1$response->assertJsonValidationErrors(array $data, $responseKey = 'errors');
更通用的 assertInvalid 方法可用于断言响应有作为 JSON 返回的验证错误,或有错误闪存到会话存储中。
assertJsonValidationErrorFor
断言响应对于给定键有任何 JSON 验证错误
1$response->assertJsonValidationErrorFor(string $key, $responseKey = 'errors');
assertMethodNotAllowed
断言响应具有方法不被允许 (405) HTTP 状态码
1$response->assertMethodNotAllowed();
assertMovedPermanently
断言响应具有永久移动 (301) HTTP 状态码
1$response->assertMovedPermanently();
assertLocation
断言响应的 Location 头中具有给定的 URI 值
1$response->assertLocation($uri);
assertContent
断言给定的字符串与响应内容匹配
1$response->assertContent($value);
assertNoContent
断言响应具有给定的 HTTP 状态码且没有内容
1$response->assertNoContent($status = 204);
assertStreamed
断言响应是流式响应
1$response->assertStreamed();
assertStreamedContent
断言给定的字符串与流式响应内容匹配
1$response->assertStreamedContent($value);
assertNotFound
断言响应具有未找到 (404) HTTP 状态码
1$response->assertNotFound();
assertOk
断言响应具有 200 HTTP 状态码
1$response->assertOk();
assertPaymentRequired
断言响应具有需要付款 (402) HTTP 状态码
1$response->assertPaymentRequired();
assertPlainCookie
断言响应包含给定的未加密 cookie
1$response->assertPlainCookie($cookieName, $value = null);
assertRedirect
断言响应是重定向到给定 URI
1$response->assertRedirect($uri = null);
assertRedirectBack
断言响应是否重定向回上一页
1$response->assertRedirectBack();
assertRedirectBackWithErrors
断言响应是否重定向回上一页,且会话具有给定的错误
1$response->assertRedirectBackWithErrors(2 array $keys = [], $format = null, $errorBag = 'default'3);
assertRedirectBackWithoutErrors
断言响应是否重定向回上一页,且会话不包含任何错误消息
1$response->assertRedirectBackWithoutErrors();
assertRedirectContains
断言响应是否重定向到包含给定字符串的 URI
1$response->assertRedirectContains($string);
assertRedirectToRoute
断言响应是重定向到给定的命名路由
1$response->assertRedirectToRoute($name, $parameters = []);
assertRedirectToSignedRoute
断言响应是重定向到给定的签名路由
1$response->assertRedirectToSignedRoute($name = null, $parameters = []);
assertRequestTimeout
断言响应具有请求超时 (408) HTTP 状态码
1$response->assertRequestTimeout();
assertSee
断言响应中包含给定的字符串。此断言将自动转义给定的字符串,除非你传入 false 作为第二个参数
1$response->assertSee($value, $escape = true);
assertSeeInOrder
断言响应中按顺序包含给定的字符串。此断言将自动转义给定的字符串,除非你传入 false 作为第二个参数
1$response->assertSeeInOrder(array $values, $escape = true);
assertSeeText
断言响应文本中包含给定的字符串。此断言将自动转义给定的字符串,除非你传入 false 作为第二个参数。在进行断言之前,响应内容将传递给 PHP 的 strip_tags 函数
1$response->assertSeeText($value, $escape = true);
assertSeeTextInOrder
断言响应文本中按顺序包含给定的字符串。此断言将自动转义给定的字符串,除非你传入 false 作为第二个参数。在进行断言之前,响应内容将传递给 PHP 的 strip_tags 函数
1$response->assertSeeTextInOrder(array $values, $escape = true);
assertServerError
断言响应具有服务器错误 (>= 500, < 600) HTTP 状态码
1$response->assertServerError();
assertServiceUnavailable
断言响应具有“服务不可用” (503) HTTP 状态码
1$response->assertServiceUnavailable();
assertSessionHas
断言会话包含给定的一段数据
1$response->assertSessionHas($key, $value = null);
如果需要,可以将闭包作为第二个参数提供给 assertSessionHas 方法。如果闭包返回 true,则断言通过
1$response->assertSessionHas($key, function (User $value) {2 return $value->name === 'Taylor Otwell';3});
assertSessionHasInput
断言会话在闪存输入数组中具有给定的值
1$response->assertSessionHasInput($key, $value = null);
如果需要,可以将闭包作为第二个参数提供给 assertSessionHasInput 方法。如果闭包返回 true,则断言通过
1use Illuminate\Support\Facades\Crypt;2 3$response->assertSessionHasInput($key, function (string $value) {4 return Crypt::decryptString($value) === 'secret';5});
assertSessionHasAll
断言会话包含给定的键/值对数组
1$response->assertSessionHasAll(array $data);
例如,如果你的应用程序会话包含 name 和 status 键,你可以像这样断言两者都存在且具有指定的值
1$response->assertSessionHasAll([2 'name' => 'Taylor Otwell',3 'status' => 'active',4]);
assertSessionHasErrors
断言会话包含给定 $keys 的错误。如果 $keys 是关联数组,则断言会话对于每个字段(键)包含特定的错误消息(值)。此方法应在测试将验证错误闪存到会话而不是以 JSON 结构返回它们的路由时使用
1$response->assertSessionHasErrors(2 array $keys = [], $format = null, $errorBag = 'default'3);
例如,要断言 name 和 email 字段有闪存到会话的验证错误消息,你可以像这样调用 assertSessionHasErrors 方法
1$response->assertSessionHasErrors(['name', 'email']);
或者,你可以断言给定字段有特定的验证错误消息
1$response->assertSessionHasErrors([2 'name' => 'The given name was invalid.'3]);
更通用的 assertInvalid 方法可用于断言响应有作为 JSON 返回的验证错误,或有错误闪存到会话存储中。
assertSessionHasErrorsIn
断言会话在特定的错误包中包含给定 $keys 的错误。如果 $keys 是关联数组,则断言会话对于错误包中的每个字段(键)包含特定的错误消息(值)
1$response->assertSessionHasErrorsIn($errorBag, $keys = [], $format = null);
assertSessionHasNoErrors
断言会话没有验证错误
1$response->assertSessionHasNoErrors();
assertSessionDoesntHaveErrors
断言会话对于给定键没有验证错误
1$response->assertSessionDoesntHaveErrors($keys = [], $format = null, $errorBag = 'default');
更通用的 assertValid 方法可用于断言响应没有作为 JSON 返回的验证错误,并且没有错误闪存到会话存储中。
assertSessionMissing
断言会话不包含给定的键
1$response->assertSessionMissing($key);
assertStatus
断言响应具有给定的 HTTP 状态码
1$response->assertStatus($code);
assertSuccessful
断言响应具有成功 (>= 200 且 < 300) HTTP 状态码
1$response->assertSuccessful();
assertTooManyRequests
断言响应具有过多请求 (429) HTTP 状态码
1$response->assertTooManyRequests();
assertUnauthorized
断言响应具有未经授权 (401) HTTP 状态码
1$response->assertUnauthorized();
assertUnprocessable
断言响应具有无法处理的实体 (422) HTTP 状态码
1$response->assertUnprocessable();
assertUnsupportedMediaType
断言响应具有不支持的媒体类型 (415) HTTP 状态码
1$response->assertUnsupportedMediaType();
assertValid
断言响应对于给定键没有验证错误。此方法可用于断言验证错误作为 JSON 结构返回或验证错误已闪存到会话的响应
1// Assert that no validation errors are present...2$response->assertValid();3 4// Assert that the given keys do not have validation errors...5$response->assertValid(['name', 'email']);
assertInvalid
断言响应对于给定键有验证错误。此方法可用于断言验证错误作为 JSON 结构返回或验证错误已闪存到会话的响应
1$response->assertInvalid(['name', 'email']);
你还可以断言给定键有特定的验证错误消息。执行此操作时,你可以提供完整消息或消息的一小部分
1$response->assertInvalid([2 'name' => 'The name field is required.',3 'email' => 'valid email address',4]);
如果你想断言给定字段是唯一有验证错误的字段,可以使用 assertOnlyInvalid 方法
1$response->assertOnlyInvalid(['name', 'email']);
assertViewHas
断言响应视图包含给定的数据
1$response->assertViewHas($key, $value = null);
将闭包作为第二个参数传递给 assertViewHas 方法,将允许你检查并对特定视图数据进行断言
1$response->assertViewHas('user', function (User $user) {2 return $user->name === 'Taylor';3});
此外,视图数据可以作为响应对象上的数组变量进行访问,从而方便地检查它
1expect($response['name'])->toBe('Taylor');
1$this->assertEquals('Taylor', $response['name']);
assertViewHasAll
断言响应视图具有给定的数据列表
1$response->assertViewHasAll(array $data);
此方法可用于断言视图简单地包含匹配给定键的数据
1$response->assertViewHasAll([2 'name',3 'email',4]);
或者,你可以断言视图数据存在且具有特定值
1$response->assertViewHasAll([2 'name' => 'Taylor Otwell',4]);
assertViewIs
断言路由返回了给定的视图
1$response->assertViewIs($value);
assertViewMissing
断言给定的数据键未提供给应用程序响应中返回的视图
1$response->assertViewMissing($key);
身份验证断言
Laravel 还提供了多种与身份验证相关的断言,你可以在应用程序的特性测试中使用。请注意,这些方法是在测试类本身上调用的,而不是在 get 和 post 等方法返回的 Illuminate\Testing\TestResponse 实例上调用的。
assertAuthenticated
断言用户已通过身份验证
1$this->assertAuthenticated($guard = null);
assertGuest
断言用户未通过身份验证
1$this->assertGuest($guard = null);
assertAuthenticatedAs
断言特定用户已通过身份验证
1$this->assertAuthenticatedAs($user, $guard = null);
验证断言
Laravel 提供了两个主要的与验证相关的断言,你可以使用它们来确保请求中提供的数据是有效的或无效的。
assertValid
断言响应对于给定键没有验证错误。此方法可用于断言验证错误作为 JSON 结构返回或验证错误已闪存到会话的响应
1// Assert that no validation errors are present...2$response->assertValid();3 4// Assert that the given keys do not have validation errors...5$response->assertValid(['name', 'email']);
assertInvalid
断言响应对于给定键有验证错误。此方法可用于断言验证错误作为 JSON 结构返回或验证错误已闪存到会话的响应
1$response->assertInvalid(['name', 'email']);
你还可以断言给定键有特定的验证错误消息。执行此操作时,你可以提供完整消息或消息的一小部分
1$response->assertInvalid([2 'name' => 'The name field is required.',3 'email' => 'valid email address',4]);