跳至内容

HTTP 测试

介绍

Laravel 提供了非常流畅的 API,用于向应用程序发出 HTTP 请求并检查响应。例如,看一下下面定义的功能测试:

1<?php
2 
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(): void
13 {
14 $response = $this->get('/');
15 
16 $response->assertStatus(200);
17 }
18}

get方法GET向应用程序发出请求,同时该assertStatus方法断言返回的响应应该具有给定的 HTTP 状态代码。除了这个简单的断言之外,Laravel 还包含各种断言,用于检查响应头、内容、JSON 结构等。

发出请求

要向您的应用发出请求,您可以在测试中调用getpostputpatchdelete方法。这些方法实际上不会向您的应用发出“真正的” HTTP 请求。相反,整个网络请求都是在内部模拟的。

测试请求方法不返回实例,而是Illuminate\Http\Response返回的实例Illuminate\Testing\TestResponse,它提供了各种有用的断言,允许您检查应用程序的响应:

1<?php
2 
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(): void
13 {
14 $response = $this->get('/');
15 
16 $response->assertStatus(200);
17 }
18}

一般来说,每个测试应该只向应用程序发出一个请求。如果在单个测试方法中执行多个请求,可能会出现意外行为。

为了方便起见,运行测试时会自动禁用 CSRF 中间件。

自定义请求标头

您可以使用该withHeaders方法在请求发送到应用程序之前自定义请求的标头。此方法允许您向请求添加任何您想要的自定义标头:

1<?php
2 
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(): void
13 {
14 $response = $this->withHeaders([
15 'X-Header' => 'Value',
16 ])->post('/user', ['name' => 'Sally']);
17 
18 $response->assertStatus(201);
19 }
20}

曲奇饼

您可以使用withCookiewithCookies方法在发出请求之前设置 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(): void
10 {
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<?php
2 
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(): void
10 {
11 $response = $this->withSession(['banned' => false])->get('/');
12 
13 //
14 }
15}

Laravel 的会话通常用于维护当前已验证用户的状态。因此,actingAs辅助方法提供了一种简单的方法来将给定用户验证为当前用户。例如,我们可以使用模型Factories来生成并验证用户:

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(): void
11 {
12 $user = User::factory()->create();
13 
14 $response = $this->actingAs($user)
15 ->withSession(['banned' => false])
16 ->get('/');
17 
18 //
19 }
20}

您还可以通过将守卫名称作​​为第二个参数传递给该方法来指定应该使用哪个守卫来验证给定用户actingAs。传递给该actingAs方法的守卫也将成为测试期间的默认守卫:

1$this->actingAs($user, 'web')

调试响应

向您的应用程序发出测试请求后,可以使用dumpdumpHeadersdumpSession方法来检查和调试响应内容:

1<?php
2 
3test('basic test', function () {
4 $response = $this->get('/');
5 
6 $response->dumpHeaders();
7 
8 $response->dumpSession();
9 
10 $response->dump();
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(): void
13 {
14 $response = $this->get('/');
15 
16 $response->dumpHeaders();
17 
18 $response->dumpSession();
19 
20 $response->dump();
21 }
22}

或者,您可以使用ddddHeadersddBodyddJsonddSession方法来转储有关响应的信息,然后停止执行:

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(): void
13 {
14 $response = $this->get('/');
15 
16 $response->dd();
17 $response->ddHeaders();
18 $response->ddBody();
19 $response->ddJson();
20 $response->ddSession();
21 }
22}

异常处理

有时您可能需要测试应用程序是否抛出了特定的异常。为此,您可以通过外观“伪造”异常处理程序Exceptions。伪造异常处理程序后,您可以使用assertReportedassertNotReported方法对请求期间抛出的异常进行断言:

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 TestCase
10{
11 /**
12 * A basic test example.
13 */
14 public function test_exception_is_thrown(): void
15 {
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::class
4);

如果您想要检查并针对抛出的异常做出断言,您可以提供一个闭包作为该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 及其响应的辅助方法。例如,jsongetJsonpostJsonputJsonpatchJsondeleteJson方法optionsJson可用于使用各种 HTTP 动词发出 JSON 请求。您还可以轻松地将数据和标头传递给这些方法。首先,让我们编写一个测试来发出POST请求/api/user并断言是否返回了预期的 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(): void
13 {
14 $response = $this->postJson('/api/user', ['name' => 'Sally']);
15 
16 $response
17 ->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(): void
13 {
14 $response = $this->postJson('/user', ['name' => 'Sally']);
15 
16 $response
17 ->assertStatus(201)
18 ->assertExactJson([
19 'created' => true,
20 ]);
21 }
22}

断言 JSON 路径

如果您想验证 JSON 响应是否包含指定路径中的给定数据,您应该使用该assertJsonPath方法:

1<?php
2 
3test('asserting a json path value', function () {
4 $response = $this->postJson('/user', ['name' => 'Sally']);
5 
6 $response
7 ->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(): void
13 {
14 $response = $this->postJson('/user', ['name' => 'Sally']);
15 
16 $response
17 ->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')
10 ->where('email', fn (string $email) => str($email)->is('victoria@gmail.com'))
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 $response
11 ->assertJson(fn (AssertableJson $json) =>
12 $json->where('id', 1)
13 ->where('name', 'Victoria Faith')
14 ->where('email', fn (string $email) => str($email)->is('victoria@gmail.com'))
15 ->whereNot('status', 'pending')
16 ->missing('password')
17 ->etc()
18 );
19}

理解etc方法

在上面的示例中,你可能注意到我们etc在断言链的末尾调用了该方法。此方法告知 Laravel,JSON 对象上可能存在其他属性。如果etc不使用该方法,并且 JSON 对象上存在你未对其进行断言的其他属性,则测试将失败。

此行为背后的意图是强制您明确地对属性做出断言或通过方法明确地允许其他属性,从而防止您无意中泄露 JSON 响应中的敏感信息etc

但是,您应该注意,etc断言链中不包含该方法并不能确保不会将其他属性添加到嵌套在 JSON 对象中的数组中。该方法仅确保在调用etc该方法的嵌套级别中不存在任何其他属性。etc

断言属性存在/不存在

要断言某个属性存在或不存在,可以使用hasmissing方法:

1$response->assertJson(fn (AssertableJson $json) =>
2 $json->has('data')
3 ->missing('message')
4);

此外,hasAllmissingAll方法允许同时断言多个属性的存在或不存在:

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')
7 ->where('email', fn (string $email) => str($email)->is('victoria@gmail.com'))
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')
8 ->where('email', fn (string $email) => str($email)->is('victoria@gmail.com'))
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')
7 ->where('email', fn (string $email) => str($email)->is('victoria@gmail.com'))
8 ->missing('password')
9 ->etc()
10 )
11 );

断言 JSON 类型

您可能只想断言 JSON 响应中的属性属于特定类型。该类Illuminate\Testing\Fluent\AssertableJson提供了whereTypewhereAllType方法来实现这一点:

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识别以下类型:stringintegerdoublebooleanarraynull

测试文件上传

该类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 TestCase
10{
11 public function test_avatars_can_be_uploaded(): void
12 {
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}

如果您想断言给定的文件不存在,您可以使用外观assertMissing提供的方法Storage

1Storage::fake('avatars');
2 
3// ...
4 
5Storage::disk('avatars')->assertMissing('missing.jpg');

虚假文件定制

fake当使用类提供的方法创建文件时UploadedFile,您可以指定图像的宽度、高度和大小(以千字节为单位),以便更好地测试应用程序的验证规则:

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<?php
2 
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(): void
10 {
11 $view = $this->view('welcome', ['name' => 'Taylor']);
12 
13 $view->assertSee('Taylor');
14 }
15}

此类TestView提供以下断言方法assertSee、、、、、assertSeeInOrderassertSeeTextassertSeeTextInOrderassertDontSeeassertDontSeeText

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\Testing\TestResponse类提供了多种自定义断言方法,您可以在测试应用程序时使用它们。您可以在jsongetpostputdelete测试方法返回的响应中访问这些断言:

断言已接受

断言响应具有已接受(202)HTTP 状态代码:

1$response->assertAccepted();

断言错误请求

断言响应具有错误请求(400)HTTP 状态代码:

1$response->assertBadRequest();

assertClientError

断言响应具有客户端错误(>= 400,< 500)HTTP 状态代码:

1$response->assertClientError();

断言冲突

断言响应存在冲突(409)HTTP 状态代码:

1$response->assertConflict();

断言响应包含给定的 cookie:

1$response->assertCookie($cookieName, $value = null);

断言响应包含给定的 cookie 并且它已过期:

1$response->assertCookieExpired($cookieName);

断言响应包含给定的 cookie 并且它没有过期:

1$response->assertCookieNotExpired($cookieName);

断言响应不包含给定的 cookie:

1$response->assertCookieMissing($cookieName);

断言已创建

断言响应具有 201 HTTP 状态代码:

1$response->assertCreated();

断言不要看

断言给定的字符串不包含在应用程序返回的响应中。除非你传递第二个参数,否则此断言将自动转义给定的字符串false

1$response->assertDontSee($value, $escape = true);

断言DontSeeText

断言给定的字符串不包含在响应文本中。除非传递第二个参数,否则此断言将自动转义给定的字符串。此方法会在进行断言之前false将响应内容传递给PHP 函数:strip_tags

1$response->assertDontSeeText($value, $escape = true);

断言下载

断言响应是“下载”。通常,这意味着返回响应的调用路由返回了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 结构中的键,则此方法将失败。

断言禁止

断言响应具有禁止(403)HTTP 状态代码:

1$response->assertForbidden();

断言已找到

断言响应具有找到(302)HTTP 状态代码:

1$response->assertFound();

assertGone

断言响应具有已消失(410)HTTP 状态代码:

1$response->assertGone();

断言头

断言响应中存在给定的标头和值:

1$response->assertHeader($headerName, $value = null);

assertHeaderMissing

断言响应中不存在给定的标头:

1$response->assertHeaderMissing($headerName);

断言内部服务器错误

断言响应具有“内部服务器错误”(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);

断言Json缺失验证错误

断言响应对于给定的键没有 JSON 验证错误:

1$response->assertJsonMissingValidationErrors($keys);

更通用的assertValid方法可用于断言响应没有以 JSON 形式返回的验证错误,并且没有错误闪现到会话存储。

assertJsonPath

断言响应在指定路径包含给定的数据:

1$response->assertJsonPath($path, $expectedValue);

例如,如果您的应用程序返回以下 JSON 响应:

1{
2 "user": {
3 "name": "Steve Schoger"
4 }
5}

您可以断言对象name的属性user与给定值匹配,如下所示:

1$response->assertJsonPath('user.name', 'Steve Schoger');

assertJsonMissingPath

断言响应不包含给定的路径:

1$response->assertJsonMissingPath($path);

例如,如果您的应用程序返回以下 JSON 响应:

1{
2 "user": {
3 "name": "Steve Schoger"
4 }
5}

您可以断言它不包含email该对象的属性user

1$response->assertJsonMissingPath('user.email');

assertJson结构

断言响应具有给定的 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');

断言方法不允许

断言响应具有不允许的方法(405)HTTP 状态代码:

1$response->assertMethodNotAllowed();

断言永久移动

断言响应具有永久移动(301)HTTP 状态代码:

1$response->assertMovedPermanently();

断言位置

断言响应在Location标头中具有给定的 URI 值:

1$response->assertLocation($uri);

断言内容

断言给定的字符串与响应内容匹配:

1$response->assertContent($value);

断言无内容

断言响应具有给定的 HTTP 状态代码并且没有内容:

1$response->assertNoContent($status = 204);

assertStreamed

断言响应是流响应:

1$response->assertStreamed();

断言流内容

断言给定的字符串与流响应内容匹配:

1$response->assertStreamedContent($value);

断言未找到

断言响应具有未找到(404)HTTP 状态代码:

1$response->assertNotFound();

断言Ok

断言响应具有 200 HTTP 状态代码:

1$response->assertOk();

断言付款​​要求

断言响应具有需要付款(402)HTTP 状态代码:

1$response->assertPaymentRequired();

断言响应包含给定的未加密 cookie:

1$response->assertPlainCookie($cookieName, $value = null);

断言重定向

断言响应是重定向到给定的 URI:

1$response->assertRedirect($uri = null);

assertRedirectBack

断言响应是否重定向回上一页:

1$response->assertRedirectBack();

断言重定向包含

断言响应是否重定向到包含给定字符串的 URI:

1$response->assertRedirectContains($string);

assertRedirectToRoute

断言响应是重定向到给定的命名路由

1$response->assertRedirectToRoute($name, $parameters = []);

assertRedirectToSignedRoute

断言响应是重定向到给定的签名路由

1$response->assertRedirectToSignedRoute($name = null, $parameters = []);

断言请求超时

断言响应具有请求超时(408)HTTP 状态代码:

1$response->assertRequestTimeout();

断言

断言给定的字符串包含在响应中。除非你传递第二个参数,否则此断言将自动转义给定的字符串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);

断言服务器错误

断言响应具有服务器错误(>= 500 ,< 600)HTTP 状态代码:

1$response->assertServerError();

断言服务不可用

断言响应具有“服务不可用”(503)HTTP 状态代码:

1$response->assertServiceUnavailable();

断言会话有

断言会话包含给定的数据:

1$response->assertSessionHas($key, $value = null);

如果需要,可以将闭包作为assertSessionHas方法的第二个参数。如果闭包返回以下内容,则断言将通过true

1$response->assertSessionHas($key, function (User $value) {
2 return $value->name === 'Taylor Otwell';
3});

断言会话有输入

断言会话在闪存的输入数组中具有给定值:

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});

断言SessionHasAll

断言会话包含给定的键/值对数组:

1$response->assertSessionHasAll(array $data);

例如,如果您的应用程序会话包含namestatus键,您可以断言两者都存在并具有指定的值,如下所示:

1$response->assertSessionHasAll([
2 'name' => 'Taylor Otwell',
3 'status' => 'active',
4]);

断言会话有错误

断言会话中存在给定 的错误$keys。如果$keys是关联数组,则断言会话中每个字段(键)都包含特定的错误消息(值)。在测试将验证错误闪现到会话中的路由时,应使用此方法,而不是将其作为 JSON 结构返回:

1$response->assertSessionHasErrors(
2 array $keys = [], $format = null, $errorBag = 'default'
3);

例如,为了断言nameemail字段具有闪现到会话的验证错误消息,您可以assertSessionHasErrors像这样调用该方法:

1$response->assertSessionHasErrors(['name', 'email']);

或者,您可以断言给定字段具有特定的验证错误消息:

1$response->assertSessionHasErrors([
2 'name' => 'The given name was invalid.'
3]);

更通用的assertInvalid方法可用于断言响应具有以 JSON 形式返回的验证错误错误已闪现到会话存储。

断言会话有错误

断言会话$keys在特定错误包中包含给定错误。如果$keys是关联数组,则断言会话在错误包中为每个字段(键)包含一个特定的错误消息(值):

1$response->assertSessionHasErrorsIn($errorBag, $keys = [], $format = null);

断言会话无错误

断言会话没有验证错误:

1$response->assertSessionHasNoErrors();

断言会话没有错误

断言会话对于给定的键没有验证错误:

1$response->assertSessionDoesntHaveErrors($keys = [], $format = null, $errorBag = 'default');

更通用的assertValid方法可用于断言响应没有以 JSON 形式返回的验证错误,并且没有错误闪现到会话存储。

断言会话缺失

断言会话不包含给定的键:

1$response->assertSessionMissing($key);

断言状态

断言响应具有给定的 HTTP 状态代码:

1$response->assertStatus($code);

断言成功

断言响应具有成功(>= 200 且 < 300)的 HTTP 状态代码:

1$response->assertSuccessful();

断言请求过多

断言响应具有过多请求(429)HTTP 状态代码:

1$response->assertTooManyRequests();

断言未授权

断言响应具有未授权(401)HTTP 状态代码:

1$response->assertUnauthorized();

断言不可处理

断言响应具有无法处理的实体(422)HTTP 状态代码:

1$response->assertUnprocessable();

断言不支持的媒体类型

断言响应具有不受支持的媒体类型(415)HTTP 状态代码:

1$response->assertUnsupportedMediaType();

断言有效

断言响应中不存在给定键的验证错误。此方法可用于断言验证错误以 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']);

断言无效

断言响应中存在针对给定键的验证错误。此方法可用于断言验证错误以 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',
3 'email' => 'taylor@example.com,',
4]);

assertViewIs

断言给定的视图是由路线返回的:

1$response->assertViewIs($value);

assertViewMissing

断言给定的数据键不可用于应用程序响应中返回的视图:

1$response->assertViewMissing($key);

身份验证断言

Laravel 还提供了各种与身份验证相关的断言,您可以在应用程序的功能测试中使用它们。请注意,这些方法是在测试类本身上调用的,而不是Illuminate\Testing\TestResponse在诸如get和 等方法返回的实例上调用的post

断言已认证

断言用户已经过身份验证:

1$this->assertAuthenticated($guard = null);

断言访客

断言用户未经过身份验证:

1$this->assertGuest($guard = null);

断言已认证

断言特定用户已通过身份验证:

1$this->assertAuthenticatedAs($user, $guard = null);

验证断言

Laravel 提供了两个主要的验证相关断言,您可以使用它们来确保请求中提供的数据有效或无效。

断言有效

断言响应中不存在给定键的验证错误。此方法可用于断言验证错误以 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']);

断言无效

断言响应中存在针对给定键的验证错误。此方法可用于断言验证错误以 JSON 结构返回或已将验证错误闪现到会话中的响应:

1$response->assertInvalid(['name', 'email']);

您还可以断言给定键具有特定的验证错误消息。执行此操作时,您可以提供完整消息或仅提供消息的一小部分:

1$response->assertInvalid([
2 'name' => 'The name field is required.',
3 'email' => 'valid email address',
4]);