Laravel 提供了一个非常流畅的 API,用于向您的应用程序发起 HTTP 请求并检查响应。例如,请看下面定义的特性测试:
<?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);
}
}通常情况下,您的每个测试应只向您的应用程序发出一个请求。如果在单个测试方法中执行了多个请求,可能会发生意外行为。
[!NOTE]
为方便起见,在运行测试时,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);
}
}您可以使用 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('/');
//
}
}Laravel 提供了多个辅助函数,用于在 HTTP 测试期间与会话交互。首先,你可以使用 withSession 方法将会话数据设置为给定数组。这对于在向应用发出请求之前,将会话加载数据非常有用:
<?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 的会话通常用于维护当前已认证用户的状态。因此,actingAs 辅助方法提供了一种简单的方式来将给定用户认证为当前用户。例如,我们可以使用 模型工厂 来生成并认证用户:
<?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('/');
//
}
}你也可以通过将守卫名称作为第二个参数传递给 actingAs 方法,来指定应该使用哪个守卫认证给定用户。提供给 actingAs 方法的守卫在测试期间也将成为默认守卫:
$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 门面“模拟”异常处理程序。一旦异常处理程序被模拟,您就可以利用 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 方法可用于断言给定闭包中的代码不会抛出任何异常:
上述内容意味着您不能直接从 @throws PHPDoc 标签中使用 assertDoesntThrow 方法。相反,您应该将整个断言置于提供给 assertDoesntThrow 方法的闭包内。这确保了被测代码抛出的任何异常都被断言捕获,从而防止它们进一步传播。
$this->assertDoesntThrow(fn () => (new ProcessOrder)->execute());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']);[!NOTE]
该assertJson方法将响应转换为数组,以验证给定数组是否存在于应用程序返回的 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,
]);
}
}如果您想验证 JSON 响应在指定路径包含给定数据,您应该使用 assertJsonPath 方法:
<?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 方法也接受一个闭包,该闭包可用于动态判断断言是否通过:
$response->assertJsonPath('team.owner.name', fn (string $name) => strlen($name) >= 3);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('victoria@gmail.com'))
->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('victoria@gmail.com'))
->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 响应:
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('victoria@gmail.com'))
->missing('password')
->etc()
)
);有时,你的应用程序的路由会返回 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('victoria@gmail.com'))
->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('victoria@gmail.com'))
->missing('password')
->etc()
)
);您可能只想断言 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 方法识别以下类型: 字符串, 整型, 双精度, 布尔型, 数组, 和 空值.
Illuminate\Http\UploadedFile 类提供一个 fake 方法,可用于生成用于测试的模拟文件或图像。这,结合 Storage 门面的 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());
}
}如果您想断言某个文件不存在,可以使用 assertMissing 方法,它由 Storage 门面提供:
Storage::fake('avatars');
// ...
Storage::disk('avatars')->assertMissing('missing.jpg');使用 UploadedFile 类提供的 fake 方法创建文件时,你可以指定图片的宽度、高度和大小(单位为千字节),以便更好地测试你的应用程序的验证规则:
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 提供的全局错误包。要用错误消息填充错误包,你可以使用 withViewErrors 方法:
$view = $this->withViewErrors([
'name' => ['Please provide a valid name.']
])->view('form');
$view->assertSee('Please provide a valid name.');如果需要,你可以使用 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 测试方法返回的响应访问这些断言:
assertAccepted
assertBadRequest
assertClientError
assertConflict
assertCookie
assertCookieExpired
assertCookieNotExpired
assertCookieMissing
assertCreated
assertDontSee
assertDontSeeText
assertDownload
assertExactJson
assertExactJsonStructure
assertForbidden
assertFound
assertGone
assertHeader
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
确认响应具有已接受 (202) HTTP 状态码:
$response->assertAccepted();断言响应是一个错误请求 (400) HTTP 状态码:
$response->assertBadRequest();断言响应具有客户端错误 (>= 400, < 500) HTTP 状态码:
$response->assertClientError();断言响应具有冲突 (409) HTTP 状态码:
$response->assertConflict();断言响应包含给定的 cookie:
$response->assertCookie($cookieName, $value = null);断言响应包含给定的 cookie 且它已过期:
$response->assertCookieExpired($cookieName);断言响应包含给定的 cookie 且未过期:
$response->assertCookieNotExpired($cookieName);断言响应不包含给定的 cookie:
$response->assertCookieMissing($cookieName);断言响应具有 201 HTTP 状态码:
$response->assertCreated();断言给定的字符串不包含在应用程序返回的响应中。此断言会自动转义给定的字符串,除非你传入第二个参数为 false:
$response->assertDontSee($value, $escape = true);断言给定字符串不包含在响应文本中。此断言会自动转义给定字符串,除非你传入第二个参数为 false。此方法会在执行断言之前,将响应内容传入 strip_tags PHP 函数:
$response->assertDontSeeText($value, $escape = true);断言响应是“下载”。通常,这意味着返回响应的被调用的路由返回了一个 Response::download 响应、BinaryFileResponse 或 Storage::download 响应:
$response->assertDownload();如果您愿意,您可以声明可下载的文件被分配了一个指定的文件名:
$response->assertDownload('image.jpg');断言响应包含与给定 JSON 数据完全一致的内容:
$response->assertExactJson(array $data);断言响应包含对给定的 JSON 结构的精确匹配:
$response->assertExactJsonStructure(array $data);这个方法是assertJsonStructure的一个更严格的变体。与assertJsonStructure不同,如果响应包含任何未明确包含在预期 JSON 结构中的键,此方法将失败。
断言响应具有禁止访问 (403) HTTP 状态码:
$response->assertForbidden();断言响应具有一个找到 (302) HTTP 状态码:
$response->assertFound();断言响应具有一个已失效 (410) HTTP 状态码:
$response->assertGone();断言给定的请求头和值存在于响应中:
$response->assertHeader($headerName, $value = null);断言给定头不在响应中:
$response->assertHeaderMissing($headerName);断言响应具有“内部服务器错误”(500) HTTP 状态码:
$response->assertInternalServerError();断言响应包含给定的 JSON 数据:
$response->assertJson(array $data, $strict = false);assertJson 方法将响应转换为数组,以验证给定数组是否存在于应用程序返回的 JSON 响应中. 因此,如果 JSON 响应中存在其他属性,只要给定片段存在,此测试仍将通过.
确保响应 JSON 在给定键处包含一个具有预期项数的数组:
$response->assertJsonCount($count, $key = null);断言响应在任意位置包含给定的 JSON 数据:
Route::get('/users', function () {
return [
'users' => [
[
'name' => 'Taylor Otwell',
],
],
];
});
$response->assertJsonFragment(['name' => 'Taylor Otwell']);断言响应 JSON 是一个数组:
$response->assertJsonIsArray();断言响应 JSON 是一个对象:
$response->assertJsonIsObject();断言响应不包含给定的 JSON 数据:
$response->assertJsonMissing(array $data);断言响应不包含精确的 JSON 数据:
$response->assertJsonMissingExact(array $data);断言响应对于给定的键没有 JSON 验证错误:
$response->assertJsonMissingValidationErrors($keys);[!NOTE]
更通用的 assertValid 方法可用于断言响应不包含以 JSON 格式返回的验证错误,并且没有错误被闪存到会话存储中。
断言响应在指定路径包含给定数据:
$response->assertJsonPath($path, $expectedValue);例如,如果您的应用程序返回以下 JSON 响应:
{
"user": {
"name": "Steve Schoger"
}
}您可以断言 user 对象的 name 属性匹配给定值,如下所示:
$response->assertJsonPath('user.name', 'Steve Schoger');断言响应不包含给定路径:
$response->assertJsonMissingPath($path);例如,如果您的应用程序返回以下 JSON 响应:
{
"user": {
"name": "Steve Schoger"
}
}您可以断言它不包含 user 对象的 email 属性:
$response->assertJsonMissingPath('user.email');断言响应具有给定的 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'
]
]
]);断言响应针对给定键包含给定的 JSON 验证错误。此方法应在断言响应时使用,其中验证错误以 JSON 结构返回,而不是作为闪存数据存储到会话中:
$response->assertJsonValidationErrors(array $data, $responseKey = 'errors');[!NOTE]
更通用的 assertInvalid 方法可用于断言响应包含以 JSON 格式返回的验证错误 或 错误已闪存到会话存储中。
断言响应针对给定键存在任何 JSON 验证错误:
$response->assertJsonValidationErrorFor(string $key, $responseKey = 'errors');断言响应具有方法不被允许 (405) HTTP 状态码:
$response->assertMethodNotAllowed();断言响应具有永久移动 (301) HTTP 状态码:
$response->assertMovedPermanently();断言响应在 Location 头部中包含给定的 URI 值:
$response->assertLocation($uri);断言给定字符串匹配响应内容:
$response->assertContent($value);断言响应具有给定的 HTTP 状态码且无内容:
$response->assertNoContent($status = 204);断言响应是一个流式响应:
$response->assertStreamed();
断言给定的字符串与流式响应内容匹配:
$response->assertStreamedContent($value);断言响应具有未找到 (404) HTTP 状态码:
$response->assertNotFound();断言响应的 HTTP 状态码为 200:
$response->assertOk();断言响应具有支付请求 (402) HTTP 状态码:
$response->assertPaymentRequired();确认响应包含给定的未加密 cookie:
$response->assertPlainCookie($cookieName, $value = null);断言响应重定向到给定的 URI:
$response->assertRedirect($uri = null);断言响应是否重定向回上一页:
$response->assertRedirectBack();断言响应是否重定向回上一页并且会话包含给定错误:
$response->assertRedirectBackWithErrors(
array $keys = [], $format = null, $errorBag = 'default'
);断言响应是否正在重定向回上一页,并且会话不包含任何错误消息:
$response->assertRedirectBackWithoutErrors();断言响应是否重定向到包含给定字符串的 URI:
$response->assertRedirectContains($string);断言响应重定向到给定命名路由:
$response->assertRedirectToRoute($name, $parameters = []);断言响应重定向到给定 签名路由:
$response->assertRedirectToSignedRoute($name = null, $parameters = []);断言响应具有请求超时 (408) HTTP 状态码:
$response->assertRequestTimeout();断言响应中包含给定字符串。此断言将自动转义给定字符串,除非你传入第二个参数 false:
$response->assertSee($value, $escape = true);断言给定字符串按顺序包含在响应中。此断言将自动转义给定字符串,除非您传入第二个参数 false:
$response->assertSeeInOrder(array $values, $escape = true);断言给定字符串包含在响应文本中。除非你传递第二个参数为 false,否则此断言将自动转义给定字符串。在进行断言之前,响应内容将被传递给 strip_tags PHP 函数:
$response->assertSeeText($value, $escape = true);断言给定字符串按顺序包含在响应文本中。此断言将自动转义给定字符串,除非您传入第二个参数 false。响应内容将在断言之前传递给 strip_tags PHP 函数:
$response->assertSeeTextInOrder(array $values, $escape = true);断言响应具有服务器错误 (>= 500 , < 600) HTTP 状态码:
$response->assertServerError();确认响应具有 "服务不可用" (503) HTTP 状态码:
$response->assertServiceUnavailable();断言会话包含给定的数据:
$response->assertSessionHas($key, $value = null);如果需要,可以提供一个闭包作为第二个参数给 assertSessionHas 方法。该断言会通过如果闭包返回 true:
$response->assertSessionHas($key, function (User $value) {
return $value->name === 'Taylor Otwell';
});断言会话在闪存输入数组中具有给定值:
$response->assertSessionHasInput($key, $value = null);如果需要,可以提供一个闭包作为 assertSessionHasInput 方法的第二个参数。如果闭包返回 true,则断言通过:
use Illuminate\Support\Facades\Crypt;
$response->assertSessionHasInput($key, function (string $value) {
return Crypt::decryptString($value) === 'secret';
});断言会话包含给定数组的键值对:
$response->assertSessionHasAll(array $data);例如,如果您的应用程序会话包含 name 和 status 键,您可以断言它们都存在并具有指定值,如下所示:
$response->assertSessionHasAll([
'name' => 'Taylor Otwell',
'status' => 'active',
]);断言会话中包含给定 $keys 的错误。如果 $keys 是一个关联数组,断言会话中包含每个字段 (键) 的特定错误消息 (值)。此方法应用于测试那些将验证错误闪存到会话中而非以 JSON 结构返回的路由:
$response->assertSessionHasErrors(
array $keys = [], $format = null, $errorBag = 'default'
);例如,要断言 name 和 email 字段具有已闪存到会话的验证错误消息,你可以像这样调用 assertSessionHasErrors 方法:
$response->assertSessionHasErrors(['name', 'email']);或者,你可以断言某个给定字段具有特定的验证错误消息:
$response->assertSessionHasErrors([
'name' => 'The given name was invalid.'
]);[!NOTE]
更通用的 assertInvalid 方法可用于断言响应返回了 JSON 格式的验证错误 或 错误已闪存到会话存储。
断言会话在特定的错误包中包含给定 $keys 的错误。如果 $keys 是一个关联数组,则断言会话在错误包中包含针对每个字段(键)的特定错误消息(值):
$response->assertSessionHasErrorsIn($errorBag, $keys = [], $format = null);确认会话没有验证错误:
$response->assertSessionHasNoErrors();断言会话对于给定的键没有验证错误:
$response->assertSessionDoesntHaveErrors($keys = [], $format = null, $errorBag = 'default');[!NOTE]
更通用的 assertValid 方法可用于断言响应没有以 JSON 格式返回的验证错误并且没有错误被闪存到会话存储。
确认会话不包含给定的键:
$response->assertSessionMissing($key);断言响应具有给定的 HTTP 状态码:
$response->assertStatus($code);断言响应具有一个成功的 (>= 200 且 < 300) HTTP 状态码:
$response->assertSuccessful();断言响应具有请求过多 (429) HTTP 状态码:
$response->assertTooManyRequests();断言响应具有未经授权的 (401) HTTP 状态码:
$response->assertUnauthorized();断言响应具有不可处理实体 (422) HTTP 状态码:
$response->assertUnprocessable();断言响应具有不支持的媒体类型 (415) HTTP 状态码:
$response->assertUnsupportedMediaType();断言响应对给定键没有验证错误。此方法可用于断言响应,其中验证错误以 JSON 结构返回,或者验证错误已闪存到会话中:
// Assert that no validation errors are present...
$response->assertValid();
// Assert that the given keys do not have validation errors...
$response->assertValid(['name', 'email']);断言响应包含针对给定键的验证错误。此方法可用于断言响应,其中验证错误以 JSON 结构返回,或验证错误已闪存到会话中:
$response->assertInvalid(['name', 'email']);您还可以断言,给定的键具有特定的验证错误消息。在这样做时,您可以提供完整的消息,或者只提供消息的一小部分:
$response->assertInvalid([
'name' => 'The name field is required.',
'email' => 'valid email address',
]);如果您想断言给定字段是唯一存在验证错误的字段,您可以使用 assertOnlyInvalid 方法:
$response->assertOnlyInvalid(['name', 'email']);断言响应视图包含给定的数据:
$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']);断言响应视图具有给定数据列表:
$response->assertViewHasAll(array $data);这个方法可用于断言视图仅包含与给定键匹配的数据:
$response->assertViewHasAll([
'name',
'email',
]);或者,您可以断言视图数据存在并具有特定值:
$response->assertViewHasAll([
'name' => 'Taylor Otwell',
'email' => 'taylor@example.com,',
]);断言给定的视图由路由返回:
$response->assertViewIs($value);断言给定的数据键未提供给应用程序响应中返回的视图:
$response->assertViewMissing($key);Laravel 还提供了各种认证相关的断言,你可以在应用的特性测试中使用。请注意,这些方法是在测试类本身上调用的,而不是由 get 和 post 等方法返回的 Illuminate\Testing\TestResponse 实例。
确保用户已通过身份验证:
$this->assertAuthenticated($guard = null);断言用户未认证:
$this->assertGuest($guard = null);断言某个特定用户已通过身份验证:
$this->assertAuthenticatedAs($user, $guard = null);Laravel 提供了两个主要的验证相关断言,你可以使用它们来确保你请求中提供的数据是有效还是无效的。
断言响应对于给定的键没有验证错误。此方法可用于断言响应,其中验证错误以 JSON 结构返回,或者验证错误已闪存到会话中:
// Assert that no validation errors are present...
$response->assertValid();
// Assert that the given keys do not have validation errors...
$response->assertValid(['name', 'email']);断言响应针对给定的键存在验证错误。此方法可用于断言响应,其中验证错误以 JSON 结构返回,或验证错误已闪存到会话中:
$response->assertInvalid(['name', 'email']);您还可以断言给定键具有特定的验证错误消息。执行此操作时,您可以提供整个消息或仅提供消息的一小部分:
$response->assertInvalid([
'name' => 'The name field is required.',
'email' => 'valid email address',
]);