HTTP 测试

未匹配的标注
本文档最新版为 11.x,旧版本可能放弃维护,推荐阅读最新版!

HTTP 测试

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
{
    /**
     * 一个基础测试示例。
     */
    public function test_the_application_returns_a_successful_response(): void
    {
        $response = $this->get('/');

        $response->assertStatus(200);
    }
}

这里的 get 方法是向应用程序发起一个 GET 请求,而 assertStatus 方法断言返回的响应状态码应为 200。

除了这个简单的断言外,Laravel 还提供了多种用于检查响应头、响应内容、JSON 结构等的断言方法。

发起请求

在测试中你可以使用 getpostputpatchdelete 方法向应用发起请求。

这些方法并不会真正通过网络发送 HTTP 请求,而是 在内部模拟整个请求流程,因此测试非常快速且不依赖外部服务。

Laravel 中的测试请求方法并不会返回 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
{
    /**
     * 一个基础的测试示例。
     */
    public function test_a_basic_request(): void
    {
        $response = $this->get('/');

        $response->assertStatus(200);
    }
}

通常来说,每个测试方法中应该只对应用发起一次请求。如果在一个测试方法中发起多个请求,可能会导致意料之外的行为。

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

自定义请求头

你可以使用 withHeaders 方法,在请求发送前自定义请求头。这允许你为请求添加任何你想要的自定义 Header:

<?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
{
    /**
     * 一个带有请求头的功能测试。
     */
    public function test_interacting_with_headers(): void
    {
        $response = $this->withHeaders([
            'X-Header' => 'Value',
        ])->post('/user', ['name' => 'Sally']);

        $response->assertStatus(201);
    }
}

Cookies

你可以使用 withCookiewithCookies 方法,在发起请求前设置 Cookie。

  • withCookie(name, value) 方法接收 Cookie 名称和值两个参数;
  • withCookies([key => value]) 方法则接收一个键值对数组:
<?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 方法的第二个参数指定使用的 guard 名称。指定的 guard 会在当前测试生命周期内成为默认 guard:

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

调试响应

在向应用程序发起测试请求之后,可以使用 dumpdumpHeadersdumpSession 方法来查看和调试响应的内容:

<?php

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

    $response->dumpHeaders();

    $response->dumpSession();

    $response->dump();
});
<?php

namespace Tests\Feature;

use Tests\TestCase;

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

        $response->dumpHeaders();

        $response->dumpSession();

        $response->dump();
    }
}

你也可以使用 dd 系列方法来输出响应信息并立即终止测试执行:

  • dd():输出整个响应
  • ddHeaders():输出响应头
  • ddBody():输出原始响应体
  • ddJson():格式化输出 JSON 响应体
  • 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
{
    /**
     * 一个基本的测试示例。
     */
    public function test_basic_test(): void
    {
        $response = $this->get('/');

        $response->dd();
        $response->ddHeaders();
        $response->ddBody();
        $response->ddJson();
        $response->ddSession();
    }
}

异常处理

有时,你可能需要测试你的应用程序是否抛出了某个特定的异常。你可以通过 Laravel 提供的 Exceptions facade 来“伪造”异常处理器,从而捕获异常并断言它的内容。

一旦异常处理器被伪造,你就可以使用 assertReportedassertNotReported 方法断言某个异常是否已被抛出并报告:

<?php

use App\Exceptions\InvalidOrderException;
use Illuminate\Support\Facades\Exceptions;

test('exception is thrown', function () {
    Exceptions::fake();

    $response = $this->get('/order/1');

    // 断言已抛出指定类型的异常
    Exceptions::assertReported(InvalidOrderException::class);

    // 使用闭包断言异常详情
    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
{
    /**
     * 一个基本的测试示例。
     */
    public function test_exception_is_thrown(): void
    {
        Exceptions::fake();

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

        // 断言已抛出指定类型的异常
        Exceptions::assertReported(InvalidOrderException::class);

         // 使用闭包断言异常内容
        Exceptions::assertReported(function (InvalidOrderException $e) {
            return $e->getMessage() === 'The order was invalid.';
        });
    }
}

assertNotReported 和 assertNothingReported 方法可用于断言请求期间未抛出给定异常或没有抛出任何异常:

Exceptions::assertNotReported(InvalidOrderException::class);

Exceptions::assertNothingReported();

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

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

此外,如果你希望确保你的应用程序未使用 PHP 语言或其使用的库中已弃用的功能,你可以在发出请求之前调用 withoutDeprecationHandling 方法。禁用弃用处理时,弃用警告将被转换为异常,从而导致你的测试失败:

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

assertThrows 方法可用于断言给定闭包中的代码抛出了指定类型的异常:

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

如果你希望检查并对所抛出的异常进行断言,可以将闭包作为 assertThrows 方法的第二个参数传入:

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

assertDoesntThrow 方法可用于断言给定闭包中的代码未抛出任何异常:

$this->assertDoesntThrow(fn () => (new ProcessOrder)->execute());

测试 JSON API

Laravel 还提供了一些辅助方法用于测试 JSON API 及其响应。例如,jsongetJsonpostJsonputJsonpatchJsondeleteJsonoptionsJson 方法可用于使用不同的 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
{
    /**
     * 一个基本的功能测试示例。
     */
    public function test_making_an_api_request(): void
    {
        $response = $this->postJson('/api/user', ['name' => 'Sally']);

        $response
            ->assertStatus(201)
            ->assertJson([
                'created' => true,
            ]);
    }
}

此外,JSON 响应数据可以像数组变量一样在响应中访问,这让你可以方便地检查 JSON 响应中返回的各个值:

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

assertJson 方法会将响应转换为数组,以验证所提供的数组是否存在于应用返回的 JSON 响应中。因此,即使 JSON 响应中还有其他属性,只要提供的片段存在,测试也会通过。

断言精确的 JSON 匹配

如前所述,assertJson 方法可用于断言 JSON 响应中包含某个 JSON 片段。如果你希望验证指定数组 与应用返回的 JSON 完全一致,则应使用 assertExactJson 方法:

<?php

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

    $response
        ->assertStatus(201)
        ->assertExactJson([
            'created' => true,
        ]);
});
<?php

namespace Tests\Feature;

use Tests\TestCase;

class ExampleTest extends TestCase
{
    /**
     * 一个基础功能测试示例。
     */
    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

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
{
    /**
     * 一个基础功能测试示例。
     */
    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 中缺失:

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 方法仅确保在调用该方法的嵌套层级中不存在额外属性

断言属性的存在 / 缺失

要断言某个属性是否存在或缺失,你可以使用 hasmissing 方法:

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

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

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

你可以使用 hasAny 方法来判断指定的一组属性中是否至少有一个存在:

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

针对 JSON 集合进行断言

通常,你的路由会返回包含多个项目的 JSON 响应,比如多个用户:

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

在这种情况下,我们可以使用 Fluent 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 集合设置作用域断言

有时,你的应用路由会返回包含命名键的 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 集合的项数和第一项的属性,不如在一次 has 调用中传入第三个参数(闭包),此时该闭包将自动作用于集合中的第一项:

$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 方法来实现这一点:

$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'])
);

whereTypewhereAllType 方法支持以下类型:stringintegerdoublebooleanarraynull

测试文件上传

Illuminate\Http\UploadedFile 类提供了一个 fake 方法,可以用于生成测试用的假文件或图片。该方法通常与 Storage facade 的 fake 方法搭配使用,从而极大简化了文件上传功能的测试流程。例如,下面的代码就可以轻松测试头像上传表单:

<?php

use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;

test('avatars can be uploaded', function () {
    Storage::fake('avatars');

    $file = UploadedFile::fake()->image('avatar.jpg');

    $response = $this->post('/avatar', [
        'avatar' => $file,
    ]);

    Storage::disk('avatars')->assertExists($file->hashName());
});
<?php

namespace Tests\Feature;

use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;

class ExampleTest extends TestCase
{
    public function test_avatars_can_be_uploaded(): void
    {
        Storage::fake('avatars');

        $file = UploadedFile::fake()->image('avatar.jpg');

        $response = $this->post('/avatar', [
            'avatar' => $file,
        ]);

        Storage::disk('avatars')->assertExists($file->hashName());
    }
}

如果你想断言某个文件不存在,可以使用 Storage facade 提供的 assertMissing 方法:

Storage::fake('avatars');

// ...

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

虚拟文件的自定义

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

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

除了创建图片之外,你还可以使用 create 方法创建任意类型的文件:

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

如有需要,你还可以传递 $mimeType 参数来显式指定该文件返回的 MIME 类型:

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

测试视图

Laravel 还允许你在不发起模拟 HTTP 请求的前提下渲染视图。在测试中,你可以通过调用 view 方法来完成这一操作。该方法接受视图名称及一个可选的数据数组,并返回一个 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 方法来解析并渲染一段原始的 Blade 模板字符串。与 view 方法类似,blade 方法返回 Illuminate\Testing\TestView 实例:

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

$view->assertSee('Taylor');

你也可以使用 component 方法来渲染一个 Blade 组件。该方法返回一个 Illuminate\Testing\TestComponent 实例:

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

$view->assertSee('Taylor');

可用的断言方法

响应断言

Laravel 的 Illuminate\Testing\TestResponse 类提供了丰富的自定义断言方法,可用于测试应用程序的 HTTP 响应。这些断言方法可以通过 jsongetpostputdelete 测试方法返回的响应对象进行调用。

assertAccepted

断言响应的 HTTP 状态码为 202 Accepted(已接受):

$response->assertAccepted();

assertBadRequest

断言响应的 HTTP 状态码为 400 Bad Request(错误请求):

$response->assertBadRequest();

assertClientError

断言响应的 HTTP 状态码属于客户端错误(范围:400–499):

$response->assertClientError();

assertConflict

断言响应的 HTTP 状态码为 409 Conflict(冲突)

$response->assertConflict();

assertCookie

断言响应中包含指定名称的 Cookie,并可选验证其值:

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

assertCookieExpired

断言响应中包含指定名称的 Cookie,且该 Cookie 已过期:

$response->assertCookieExpired($cookieName);

assertCookieNotExpired

断言响应中包含指定名称的 Cookie,且该 Cookie 尚未过期:

$response->assertCookieNotExpired($cookieName);

assertCookieMissing

断言响应中不包含指定名称的 Cookie:

$response->assertCookieMissing($cookieName);

assertCreated

断言响应的 HTTP 状态码为 201 Created(已创建):

$response->assertCreated();

assertDontSee

断言响应内容中不包含指定字符串。默认情况下该字符串会被自动转义,除非你传入第二个参数为 false

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

assertDontSeeText

断言响应的纯文本内容中不包含指定字符串。该方法会在断言前对响应内容执行 strip_tags 去除 HTML 标签:

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

assertDownload

断言响应是一个“文件下载”响应。通常意味着该响应是由 Response::downloadBinaryFileResponseStorage::download 返回的:

$response->assertDownload();

如果需要,还可以断言下载文件的名称为指定值:

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

assertExactJson

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

$response->assertExactJson(array $data);

assertExactJsonStructure

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

$response->assertExactJsonStructure(array $data);

该方法是 assertJsonStructure 的一个更严格的变体。与 assertJsonStructure 不同,如果响应包含任何未被明确包含在预期 JSON 结构中的键,该方法将失败。

assertForbidden

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

$response->assertForbidden();

assertFound

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

$response->assertFound();

assertGone

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

$response->assertGone();

assertHeader

断言给定的头和数值出现在响应中:

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

assertHeaderMissing

断言给定的头未出现在响应中:

$response->assertHeaderMissing($headerName);

assertInternalServerError

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

$response->assertInternalServerError();

assertJson

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

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

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

assertJsonCount

断言响应的 JSON 在给定的键处有一个数组,并且该数组的元素数量与预期相符:

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

assertJsonFragment

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

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

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

assertJsonIsArray

断言响应的 JSON 是一个数组:

$response->assertJsonIsArray();

assertJsonIsObject

断言响应的 JSON 是一个对象:

$response->assertJsonIsObject();

assertJsonMissing

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

$response->assertJsonMissing(array $data);

assertJsonMissingExact

断言响应不包含完全匹配的 JSON 数据:

$response->assertJsonMissingExact(array $data);

assertJsonMissingValidationErrors

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

$response->assertJsonMissingValidationErrors($keys);

可以使用更通用的 assertValid 方法来断言响应没有返回 JSON 格式的验证错误,并且没有向会话存储中闪存错误信息。

assertJsonPath

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

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

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

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

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

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

assertJsonMissingPath

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

$response->assertJsonMissingPath($path);

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

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

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

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

assertJsonStructure

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

$response->assertJsonStructure(array $structure);

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

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

你可以断言 JSON 结构符合预期,如下所示:

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

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

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

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

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

assertJsonValidationErrors

断言响应在给定键处包含指定的 JSON 验证错误。
当验证错误以 JSON 结构返回(而不是被闪存到会话中)时,应使用此方法:

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

可以使用更通用的 assertInvalid 方法来断言响应包含以 JSON 返回的验证错误,或者错误已被闪存到会话存储中。

assertJsonValidationErrorFor

断言响应在给定键处存在任意 JSON 验证错误:

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

assertMethodNotAllowed

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

$response->assertMethodNotAllowed();

assertMovedPermanently

断言响应的 HTTP 状态码为永久移动(301):

$response->assertMovedPermanently();

assertLocation

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

$response->assertLocation($uri);

assertContent

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

$response->assertContent($value);

assertNoContent

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

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

assertStreamed

断言响应是一个流式响应:

$response->assertStreamed();

assertStreamedContent

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

$response->assertStreamedContent($value);

assertNotFound

断言响应的 HTTP 状态码为未找到(404):

$response->assertNotFound();

assertOk

断言响应的 HTTP 状态码为 200:

$response->assertOk();

assertPaymentRequired

断言响应的 HTTP 状态码为需要付款(402):

$response->assertPaymentRequired();

assertPlainCookie

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

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

assertRedirect

断言响应为重定向到给定 URI:

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

assertRedirectBack

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

$response->assertRedirectBack();

assertRedirectContains

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

$response->assertRedirectContains($string);

assertRedirectToRoute

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

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

assertRedirectToSignedRoute

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

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

assertRequestTimeout

断言响应的 HTTP 状态码为请求超时(408):

$response->assertRequestTimeout();

assertSee

断言响应中包含给定字符串。除非传递第二个参数为 false,否则此断言会自动对给定字符串进行转义:

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

assertSeeInOrder

断言响应中按顺序包含给定字符串。除非传递第二个参数为 false,否则此断言会自动对给定字符串进行转义:

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

assertSeeText

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

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

assertSeeTextInOrder

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

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

assertServerError

断言响应的 HTTP 状态码为服务器错误(>= 500 且 < 600):

$response->assertServerError();

assertServiceUnavailable

断言响应的 HTTP 状态码为“服务不可用”(503):

$response->assertServiceUnavailable();

assertSessionHas

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

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

如有需要,可以将闭包作为第二个参数传递给 assertSessionHas 方法。若闭包返回 true,断言将通过:

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

assertSessionHasInput

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

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

如有需要,可以将闭包作为第二个参数传递给 assertSessionHasInput 方法。若闭包返回 true,断言将通过:

use Illuminate\Support\Facades\Crypt;

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

assertSessionHasAll

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

$response->assertSessionHasAll(array $data);

例如,如果应用的会话中包含 namestatus 键,可以这样断言它们同时存在并具有指定的值:

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

assertSessionHasErrors

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

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

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

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

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

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

更通用的 assertInvalid 方法可用于断言响应中存在以 JSON 返回的验证错误 闪存到会话存储中的错误。

assertSessionHasErrorsIn

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

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

assertSessionHasNoErrors

断言会话中没有验证错误:

$response->assertSessionHasNoErrors();

assertSessionDoesntHaveErrors

断言会话中给定字段没有验证错误:

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

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

assertSessionMissing

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

$response->assertSessionMissing($key);

assertStatus

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

$response->assertStatus($code);

assertSuccessful

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

$response->assertSuccessful();

assertTooManyRequests

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

$response->assertTooManyRequests();

assertUnauthorized

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

$response->assertUnauthorized();

assertUnprocessable

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

$response->assertUnprocessable();

assertUnsupportedMediaType

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

$response->assertUnsupportedMediaType();

assertValid

断言响应针对给定键没有验证错误。该方法可用于断言验证错误以 JSON 结构返回或以闪存方式存储于会话中的响应:

// 断言没有验证错误...
$response->assertValid();

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

assertInvalid

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

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

您也可以断言某个键具有特定的验证错误消息。
在这样做时,您可以提供完整的消息或消息的一小部分:

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

如果您想断言只有给定字段存在验证错误,可以使用 assertOnlyInvalid 方法:

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

assertViewHas

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

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

将闭包作为第二个参数传递给 assertViewHas 方法,可以让您检查并断言特定的视图数据:

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

此外,可以将视图数据作为数组变量通过响应访问,从而方便检查:

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

assertViewHasAll

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

$response->assertViewHasAll(array $data);

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

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

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

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

assertViewIs

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

$response->assertViewIs($value);

assertViewMissing

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

$response->assertViewMissing($key);

认证断言

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

assertAuthenticated

断言用户已认证:

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

assertGuest

断言用户未认证:

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

assertAuthenticatedAs

断言特定用户已认证:

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

验证断言

Laravel 提供了两个主要的验证相关断言,用于确保请求中提供的数据有效或无效。

assertValid

断言响应中给定键没有验证错误。
此方法可用于断言返回 JSON 结构的验证错误,或验证错误已闪存到会话的响应:

// 断言没有验证错误...
$response->assertValid();

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

assertInvalid

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

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

您也可以断言某个键具有特定的验证错误消息。
此时可以提供完整的错误消息或消息的一小部分:

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

本文章首发在 LearnKu.com 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://learnku.com/docs/laravel/12.x/ht...

译文地址:https://learnku.com/docs/laravel/12.x/ht...

上一篇 下一篇
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
贡献者:4
讨论数量: 0
发起讨论 只看当前版本


暂无话题~