Skip to content

HTTP 测试

介绍

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

php
<?php

test('the application returns a successful response', function () {
    $response = $this->get('/');

    $response->assertStatus(200);
});
php
<?php

namespace Tests\Feature;

use Tests\TestCase;

class ExampleTest extends TestCase
{
    /**
     * 一个基本的测试示例
     */
    public function test_the_application_returns_a_successful_response(): void
    {
        $response = $this->get('/');

        $response->assertStatus(200);
    }
}

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

提出请求

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

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

php
<?php

test('basic request', function () {
    $response = $this->get('/');

    $response->assertStatus(200);
});
php
<?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
<?php

test('interacting with headers', function () {
    $response = $this->withHeaders([
        'X-Header' => 'Value',
    ])->post('/user', ['name' => 'Sally']);

    $response->assertStatus(201);
});
php
<?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

在发出请求之前,您可以使用 withCookiewithCookies 方法来设置 cookie 值。withCookie 方法接受 cookie 名称和值作为其两个参数,而 withCookies 方法接受名称/值对数组:

php
<?php

test('interacting with cookies', function () {
    $response = $this->withCookie('color', 'blue')->get('/');

    $response = $this->withCookies([
        'color' => 'blue',
        'name' => 'Taylor',
    ])->get('/');

    //
});
php
<?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
<?php

test('interacting with the session', function () {
    $response = $this->withSession(['banned' => false])->get('/');

    //
});
php
<?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
<?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
<?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')

调试响应

向应用程序发出测试请求后,可以使用 dump``、dumpHeadersdumpSession 方法来检查和调试响应内容:

php
<?php

test('basic test', function () {
    $response = $this->get('/');

    $response->dumpHeaders();

    $response->dumpSession();

    $response->dump();
});
php
<?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->dumpHeaders();

        $response->dumpSession();

        $response->dump();
    }
}

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

php
<?php

test('basic test', function () {
    $response = $this->get('/');

    $response->ddHeaders();

    $response->ddSession();

    $response->dd();
});
php
<?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->ddHeaders();

        $response->ddSession();

        $response->dd();
    }
}

异常处理

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

php
<?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
<?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.';
        });
    }
}

assertNotReportedassertNothingReported 方法可用于断言在请求期间未引发给定异常或未引发异常:

php
Exceptions::assertNotReported(InvalidOrderException::class);

Exceptions::assertNothingReported();

您可以通过在发出请求之前调用 withoutExceptionHandling 方法来完全禁用给定请求的异常处理:

php
    $response = $this->withoutExceptionHandling()->get('/');

此外,如果您想确保您的应用程序没有利用 PHP 语言或应用程序正在使用的库已弃用的功能,您可以在发出请求之前调用 withoutDeprecationHandling 方法。禁用弃用处理后,弃用警告将转换为异常,从而导致测试失败:

php
    $response = $this->withoutDeprecationHandling()->get('/');

assertThrows 方法可用于断言给定闭包中的代码会引发指定类型的异常:

php
$this->assertThrows(
    fn () => (new ProcessOrder)->execute(),
    OrderInvalid::class
);

如果你想检查并针对抛出的异常进行断言,你可以提供一个闭包作为 assertThrows 方法的第二个参数:

php
$this->assertThrows(
    fn () => (new ProcessOrder)->execute(),
    fn (OrderInvalid $e) => $e->orderId() === 123;
);

测试 JSON API

Laravel 还提供了几个用于测试 JSON API 及其响应的帮助程序。例如,jsongetJsonpostJsonputJsonpatchJsondeleteJsonoptionsJson 方法可用于发出包含各种 HTTP 动词的 JSON 请求。你也可以轻松地将数据和标头传递给这些方法。首先,让我们编写一个测试来向 /api/user 发出 POST 请求,并断言返回了预期的 JSON 数据:

php
<?php

test('making an api request', function () {
    $response = $this->postJson('/api/user', ['name' => 'Sally']);

    $response
        ->assertStatus(201)
        ->assertJson([
            'created' => true,
         ]);
});
php
<?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 响应中返回的单个值:

php
expect($response['created'])->toBeTrue();
php
$this->assertTrue($response['created']);

NOTE

assertJson 方法将响应转换为数组,以验证给定数组是否存在于应用程序返回的 JSON 响应中。因此,如果 JSON 响应中有其他属性,只要给定片段存在,此测试仍将通过。

断言精确 JSON 匹配

如前所述,assertJson 方法可用于断言 JSON 响应中存在 JSON 片段。如果要验证给定数组是否与应用程序返回的 JSON 完全匹配,则应使用 assertExactJson 方法:

php
<?php

test('asserting an exact json match', function () {
    $response = $this->postJson('/user', ['name' => 'Sally']);

    $response
        ->assertStatus(201)
        ->assertExactJson([
            'created' => true,
        ]);
});
php
<?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 路径上断言

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

php
<?php

test('asserting a json path value', function () {
    $response = $this->postJson('/user', ['name' => 'Sally']);

    $response
        ->assertStatus(201)
        ->assertJsonPath('team.owner.name', 'Darian');
});
php
<?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);

Fluent JSON 测试

Laravel 还提供了一种流畅地测试应用程序的 JSON 响应的漂亮方法。首先,将闭包传递给 assertJson 方法。此闭包将使用 Illuminate\Testing\Fluent\AssertableJson 一个实例调用,该实例可用于对应用程序返回的 JSON 进行断言。where 方法可用于对 JSON 的特定属性进行断言,而 missing 方法可用于断言 JSON 中缺少特定属性:

php
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()
        );
});
php
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 方法的嵌套级别上不存在其他属性。

断言属性存在/缺失

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

php
    $response->assertJson(fn (AssertableJson $json) =>
        $json->has('data')
             ->missing('message')
    );

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

php
    $response->assertJson(fn (AssertableJson $json) =>
        $json->hasAll(['status', 'data'])
             ->missingAll(['message', 'code'])
    );

您可以使用 hasAny 方法来确定是否存在给定属性列表中的至少一个:

php
    $response->assertJson(fn (AssertableJson $json) =>
        $json->has('status')
             ->hasAny('data', 'message', 'code')
    );

针对 JSON 集合进行断言

通常,您的路由将返回包含多个项目(例如多个用户)的 JSON 响应:

php
    Route::get('/users', function () {
        return User::all();
    });

在这些情况下,我们可以使用 Fluent JSON 对象的 has 方法对响应中包含的用户进行断言。例如,让我们断言 JSON 响应包含三个用户。接下来,我们将使用第一种方法对集合中的第一个用户进行一些断言。第一个方法接受一个闭包,该闭包接收另一个可断言的 JSON 字符串,我们可以使用它来对 JSON 集合中的第一个对象进行断言:

php
    $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 集合断言的范围

有时,应用程序的路由将返回分配了命名键的 JSON 集合:

php
    Route::get('/users', function () {
        return [
            'meta' => [...],
            'users' => User::all(),
        ];
    })

在测试这些路由时,你可以使用 has 方法来断言集合中的项目数。此外,你可以使用 has 方法来限定一系列断言的范围:

php
    $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 集合。这样做时,闭包将被自动调用,并将范围限定为集合中的第一项:

php
    $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 类型

您可能只想断言 JSON 响应中的属性属于特定类型。该 Illuminate\Testing\Fluent\AssertableJson 类提供了 whereTypewhereAllType 方法来执行此操作:

php
    $response->assertJson(fn (AssertableJson $json) =>
        $json->whereType('id', 'integer')
             ->whereAllType([
                'users.0.name' => 'string',
                'meta' => 'array'
            ])
    );

您可以使用 | 字符指定多个类型,或者将类型数组作为第二个参数传递给 whereType 方法。如果响应值是列出的任何类型,则断言将成功:

php
    $response->assertJson(fn (AssertableJson $json) =>
        $json->whereType('name', 'string|null')
             ->whereType('id', ['string', 'integer'])
    );

whereTypewhereAllType 方法可识别以下类型:stringintegerdoublebooleanarraynull

测试文件上传

Illuminate\Http\UploadedFile 类提供了一个 fake 方法,可用于生成用于测试的虚拟文件或图像。这与 Storage Facade的 fake 方法相结合,大大简化了文件上传的测试。例如,您可以结合这两个功能来轻松测试头像上传表单:

php
<?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
<?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 方法:

php
    Storage::fake('avatars');

    // ...

    Storage::disk('avatars')->assertMissing('missing.jpg');

测试文件定制

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

php
    UploadedFile::fake()->image('avatar.jpg', $width, $height)->size(100);

除了创建图像之外,您还可以使用 create 方法创建任何其他类型的文件:

php
    UploadedFile::fake()->create('document.pdf', $sizeInKilobytes);

如果需要,你可以将 $mimeType 参数传递给方法,以显式定义文件应返回的 MIME 类型:

php
    UploadedFile::fake()->create(
        'document.pdf', $sizeInKilobytes, 'application/pdf'
    );

测试视图

Laravel 还允许您渲染视图,而无需向应用程序发出模拟 HTTP 请求。为此,您可以在测试中调用 view 方法。view 方法接受视图名称和可选的数据数组。该方法返回 Illuminate\Testing\TestView 的实例,该实例提供了多种方法来方便地对视图的内容进行断言:

php
<?php

test('a welcome view can be rendered', function () {
    $view = $this->view('welcome', ['name' => 'Taylor']);

    $view->assertSee('Taylor');
});
php
<?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 类提供以下断言方法:assertSeeassertSeeInOrderassertSeeTextassertSeeTextInOrderassertDontSeeassertDontSeeText

如果需要,你可以通过将 TestView 实例强制转换为字符串来获取原始的、渲染的视图内容:

php
    $contents = (string) $this->view('welcome');

共享错误

某些视图可能依赖于 Laravel 提供的全局错误包中共享的错误。要用错误消息激活错误包,您可以使用 withViewErrors 方法:

php
    $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 的实例:

php
    $view = $this->blade(
        '<x-component :name="$name" />',
        ['name' => 'Taylor']
    );

    $view->assertSee('Taylor');

您可以使用 component 方法对 Blade 组件进行评估和渲染。component 方法返回 Illuminate\Testing\TestComponent

php
    $view = $this->component(Profile::class, ['name' => 'Taylor']);

    $view->assertSee('Taylor');

可用断言

响应断言

Laravel Illuminate\Testing\TestResponse 的类提供了多种自定义断言方法,您可以在测试应用程序时使用这些方法。可以在 jsongetpostputdelete 测试方法返回的响应上访问这些断言:

assertBadRequest

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

php
    $response->assertBadRequest();

assertAccepted

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

php
    $response->assertAccepted();

assertConflict

断言响应具有冲突 (409) HTTP 状态代码:

php
    $response->assertConflict();

assertCookie

断言响应包含给定的 Cookie:

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

assertCookieExpired

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

php
    $response->assertCookieExpired($cookieName);

assertCookieNotExpired

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

php
    $response->assertCookieNotExpired($cookieName);

assertCookieMissing

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

php
    $response->assertCookieMissing($cookieName);

assertCreated

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

php
    $response->assertCreated();

assertDontSee

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

php
    $response->assertDontSee($value, $escaped = true);

assertDontSeeText

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

php
    $response->assertDontSeeText($value, $escaped = true);

assertDownload

断言响应是 “download”。通常,这意味着返回响应的调用路由返回 Response::download 响应、BinaryFileResponseStorage::download 响应:

php
    $response->assertDownload();

如果您愿意,您可以断言可下载文件已分配给定的文件名:

php
    $response->assertDownload('image.jpg');

assertExactJson

断言响应包含给定 JSON 数据的完全匹配项:

php
    $response->assertExactJson(array $data);

assertExactJsonStructure

断言响应包含与给定 JSON 结构完全匹配:

php
    $response->assertExactJsonStructure(array $data);

This method is a more strict variant of assertJsonStructure. In contrast with assertJsonStructure, this method will fail if the response contains any keys that aren't explicitly included in the expected JSON structure.

assertForbidden

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

php
    $response->assertForbidden();

assertFound

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

php
    $response->assertFound();

assertGone

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

php
    $response->assertGone();

assertHeader

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

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

assertHeaderMissing

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

php
    $response->assertHeaderMissing($headerName);

assertInternalServerError

断言响应具有“内部服务器错误”(500) HTTP 状态代码:

php
    $response->assertInternalServerError();

assertJson

断言响应包含给定的 JSON 数据:

php
    $response->assertJson(array $data, $strict = false);

assertJson 方法将响应转换为数组,以验证给定数组是否存在于应用程序返回的 JSON 响应中。因此,如果 JSON 响应中有其他属性,只要给定片段存在,此测试仍将通过。

assertJsonCount

断言响应 JSON 具有一个数组,其中包含给定键处的预期项目数:

php
    $response->assertJsonCount($count, $key = null);

assertJsonFragment

断言响应在响应中的任意位置包含给定的 JSON 数据:

php
    Route::get('/users', function () {
        return [
            'users' => [
                [
                    'name' => 'Taylor Otwell',
                ],
            ],
        ];
    });

    $response->assertJsonFragment(['name' => 'Taylor Otwell']);

assertJsonIsArray

断言响应 JSON 是一个数组:

php
    $response->assertJsonIsArray();

assertJsonIsObject

断言响应 JSON 是一个对象:

php
    $response->assertJsonIsObject();

assertJsonMissing

断言响应不包含给定的 JSON 数据:

php
    $response->assertJsonMissing(array $data);

assertJsonMissingExact

断言响应不包含确切的 JSON 数据:

php
    $response->assertJsonMissingExact(array $data);

assertJsonMissingValidationErrors

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

php
    $response->assertJsonMissingValidationErrors($keys);

NOTE

更通用的 assertValid 方法可用于断言响应没有作为 JSON 返回的验证错误,并且没有错误被刷入会话存储。

assertJsonPath

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

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

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

json
{
    "user": {
        "name": "Steve Schoger"
    }
}

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

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

assertJsonMissingPath

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

php
    $response->assertJsonMissingPath($path);

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

json
{
    "user": {
        "name": "Steve Schoger"
    }
}

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

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

assertJsonStructure

断言响应具有给定的 JSON 结构:

php
    $response->assertJsonStructure(array $structure);

例如,如果您的应用程序返回的 JSON 响应包含以下数据

json
{
    "user": {
        "name": "Steve Schoger"
    }
}

您可以断言 JSON 结构符合您的期望,如下所示:

php
    $response->assertJsonStructure([
        'user' => [
            'name',
        ]
    ]);

有时,应用程序返回的 JSON 响应可能包含对象数组:

json
{
    "user": [
        {
            "name": "Steve Schoger",
            "age": 55,
            "location": "Earth"
        },
        {
            "name": "Mary Schoger",
            "age": 60,
            "location": "Earth"
        }
    ]
}

在这种情况下,您可以使用 * 字符对数组中所有对象的结构进行断言:

php
    $response->assertJsonStructure([
        'user' => [
            '*' => [
                 'name',
                 'age',
                 'location'
            ]
        ]
    ]);

assertJsonValidationErrors

断言响应具有给定键的给定 JSON 验证错误。在对验证错误作为 JSON 结构返回而不是闪写到会话的响应进行断言时,应使用此方法:

php
    $response->assertJsonValidationErrors(array $data, $responseKey = 'errors');

NOTE

更通用的 assertInvalid 方法可用于断言响应具有以 JSON 形式返回的验证错误**,或者**错误已刷入会话存储。

assertJsonValidationErrorFor

断言响应包含给定键的任何 JSON 验证错误:

php
    $response->assertJsonValidationErrorFor(string $key, $responseKey = 'errors');

assertMethodNotAllowed

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

php
    $response->assertMethodNotAllowed();

assertMovedPermanently

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

php
    $response->assertMovedPermanently();

assertLocation

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

php
    $response->assertLocation($uri);

assertContent

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

php
    $response->assertContent($value);

assertNoContent

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

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

assertStreamedContent

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

php
    $response->assertStreamedContent($value);

assertNotFound

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

php
    $response->assertNotFound();

assertOk

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

php
    $response->assertOk();

assertPaymentRequired

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

php
    $response->assertPaymentRequired();

assertPlainCookie

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

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

assertRedirect

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

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

assertRedirectContains

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

php
    $response->assertRedirectContains($string);

assertRedirectToRoute

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

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

assertRedirectToSignedRoute

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

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

assertRequestTimeout

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

php
    $response->assertRequestTimeout();

assertSee

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

php
    $response->assertSee($value, $escaped = true);

assertSeeInOrder

断言给定的字符串在响应中按顺序包含。此断言将自动转义给定的字符串,除非你传递第二个参数 false

php
    $response->assertSeeInOrder(array $values, $escaped = true);

assertSeeText

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

php
    $response->assertSeeText($value, $escaped = true);

assertSeeTextInOrder

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

php
    $response->assertSeeTextInOrder(array $values, $escaped = true);

assertServerError

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

php
    $response->assertServerError();

assertServiceUnavailable

断言响应具有 “Service Unavailable” (503) HTTP 状态代码:

php
    $response->assertServiceUnavailable();

assertSessionHas

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

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

如果需要,可以将闭包作为 assertSessionHas 方法的第二个参数提供。如果闭包返回 true,则断言将传递:

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

assertSessionHasInput

断言会话在 flashed input 数组中具有给定值:

php
    $response->assertSessionHasInput($key, $value = null);

如果需要,可以将闭包作为 assertSessionHasInput 方法的第二个参数提供。如果闭包返回 true,则断言将传递:

php
    use Illuminate\Support\Facades\Crypt;

    $response->assertSessionHasInput($key, function (string $value) {
        return Crypt::decryptString($value) === 'secret';
    });

assertSessionHasAll

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

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

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

php
    $response->assertSessionHasAll([
        'name' => 'Taylor Otwell',
        'status' => 'active',
    ]);

assertSessionHasErrors

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

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

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

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

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

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

NOTE

更通用的 assertInvalid 方法可用于断言响应具有以 JSON 形式返回的验证错误**,或者**错误已刷入会话存储。

assertSessionHasErrorsIn

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

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

assertSessionHasNoErrors

断言会话没有验证错误:

php
    $response->assertSessionHasNoErrors();

assertSessionDoesntHaveErrors

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

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

NOTE

更通用的 assertValid 方法可用于断言响应没有作为 JSON 返回的验证错误,并且没有错误被刷入会话存储。

assertSessionMissing

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

php
    $response->assertSessionMissing($key);

assertStatus

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

php
    $response->assertStatus($code);

assertSuccessful

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

php
    $response->assertSuccessful();

assertTooManyRequests

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

php
    $response->assertTooManyRequests();

assertUnauthorized

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

php
    $response->assertUnauthorized();

assertUnprocessable

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

php
    $response->assertUnprocessable();

assertUnsupportedMediaType

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

php
    $response->assertUnsupportedMediaType();

assertValid

断言响应没有给定键的验证错误。此方法可用于对验证错误作为 JSON 结构返回或验证错误已闪入会话的响应进行断言:

php
    // 断言不存在验证错误...
    $response->assertValid();

    // 断言给定的密钥没有验证错误...
    $response->assertValid(['name', 'email']);

assertInvalid

断言响应具有给定键的验证错误。此方法可用于对验证错误作为 JSON 结构返回或验证错误已闪入会话的响应进行断言:

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

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

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

assertViewHas

断言响应视图包含给定的数据片段:

php
    $response->assertViewHas($key, $value = null);

将闭包作为第二个参数传递给 assertViewHas 方法将允许你检查并针对特定的视图数据进行断言:

php
    $response->assertViewHas('user', function (User $user) {
        return $user->name === 'Taylor';
    });

此外,视图数据可以作为响应上的数组变量进行访问,从而可以方便地对其进行检查:

php
expect($response['name'])->toBe('Taylor');
php
$this->assertEquals('Taylor', $response['name']);

assertViewHasAll

断言响应视图具有给定的数据列表:

php
    $response->assertViewHasAll(array $data);

此方法可用于断言视图仅包含与给定键匹配的数据:

php
    $response->assertViewHasAll([
        'name',
        'email',
    ]);

或者,您可以断言视图数据存在且具有特定值:

php
    $response->assertViewHasAll([
        'name' => 'Taylor Otwell',
        'email' => 'taylor@example.com,',
    ]);

assertViewIs

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

php
    $response->assertViewIs($value);

assertViewMissing

断言给定的数据键未提供给应用程序响应中返回的视图:

php
    $response->assertViewMissing($key);

Authentication Assertions

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

assertAuthenticated

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

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

assertGuest

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

php

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

assertAuthenticatedAs

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

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

验证断言

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

assertValid

断言响应没有给定键的验证错误。此方法可用于对验证错误作为 JSON 结构返回或验证错误已闪入会话的响应进行断言:

php
    // 断言不存在验证错误...
    $response->assertValid();

    // 断言给定的密钥没有验证错误...
    $response->assertValid(['name', 'email']);

assertInvalid

断言响应具有给定键的验证错误。此方法可用于对验证错误作为 JSON 结构返回或验证错误已闪入会话的响应进行断言:

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

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

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