Laravel 8 中文文档 HTTP 测试

mark · 2021-05-09 18:08:40 · 热度: 73

介绍

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

<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Tests\TestCase;

class ExampleTest extends TestCase
{
    /**
     * 一个基础的测试实例
     *
     * @return void
     */
    public function testBasicTest()
    {
        $response = $this->get('/');

        $response->assertStatus(200);
    }
}

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

自定义请求头

您可以使用此 withHeaders 方法自定义请求的标头,然后再将其发送到应用程序。这使您可以将任何想要的自定义标头添加到请求中:

<?php

class ExampleTest extends TestCase
{
    /**
     * 一个基本的功能测试示例
     *
     * @return void
     */
    public function testBasicExample()
    {
        $response = $this->withHeaders([
            'X-Header' => 'Value',
        ])->json('POST', '/user', ['name' => 'Sally']);

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

技巧:运行测试时,将自动禁用 CSRF 中间件。

Cookies

在发送请求前你可以使用 withCookiewithCookies 方法设置cookie。withCookie 接受 cookie 的名称和值这两个参数,而 withCookies 方法接受一个名称/值对数组:

<?php

class ExampleTest extends TestCase
{
    public function testCookies()
    {
        $response = $this->withCookie('color', 'blue')->get('/');

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

调试响应

测试请求通过应用程序后,dumpdumpHeadersdumpSession 方法可以用来分析和调试响应:

<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Tests\TestCase;

class ExampleTest extends TestCase
{
    /**
     * 一个基础的测试实例
     *
     * @return void
     */
    public function testBasicTest()
    {
        $response = $this->get('/');

        $response->dumpHeaders();

        $response->dumpSession();

        $response->dump();
    }
}

Session / 身份验证

Laravel 提供了几个可在 HTTP 测试时使用 Session 的辅助函数。首先,你需要传递一个数组给 withSession 方法来设置 session 数据。这样在应用程序的测试请求发送之前,就会先去给数据加载 session:

<?php

class ExampleTest extends TestCase
{
    public function testApplication()
    {
        $response = $this->withSession(['foo' => 'bar'])
                         ->get('/');
    }
}

当然,一般使用 session 时都是用于维护用户状态,如用户认证。actingAs 辅助函数提供了简单的方法来指定的用户认证为当前用户。例如,我们可以使用 工厂模式 来生成并认证用户:

<?php

use App\Models\User;

class ExampleTest extends TestCase
{
    public function testApplication()
    {
        $user = User::factory()->create();

        $response = $this->actingAs($user)
                         ->withSession(['foo' => 'bar'])
                         ->get('/');
    }
}

你也可以通过传递看守器名称作为 actingAs 方法的第二参数以指定用户通过哪种看守器来认证:

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

测试 JSON APIs

Laravel 也提供了几个辅助函数来测试 JSON APIs 和其响应。例如,jsongetJsonpostJsonputJsonpatchJsondeleteJson,以及 optionsJson 可以被用于发送各种 HTTP 动作。你也可以轻松地将数据和请求头传递到这些方法中。首先,让我们实现一个测试示例, 发送 POST 请求到 /user,并断言返回的期望数据:

<?php

class ExampleTest extends TestCase
{
    /**
     * 一个基本的功能测试示例
     *
     * @return void
     */
    public function testBasicExample()
    {
        $response = $this->postJson('/user', ['name' => 'Sally']);

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

技巧: assertJson 将响应转换为一个数组,并利用 PHPUnit::assertArraySubset 来验证给定的数组存在于应用返回的 JSON 响应中。因此,如果 JSON 响应中有其他属性,测试仍旧会在给定数组存在的情况下通过。

此外,JSON 响应数据可以作为数组变量在响应上访问:

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

验证 JSON 完全匹配

如果你想验证给定的数组 完全 匹配应用返回的 JSON 结果,你应该使用 assertExactJson 方法:

<?php

class ExampleTest extends TestCase
{
    /**
     * 一个基本的功能测试示例
     *
     * @return void
     */
    public function testBasicExample()
    {
        $response = $this->json('POST', '/user', ['name' => 'Sally']);

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

验证 JSON 路径

如果你想验证 JSON 响应是否包含指定路径上的某些给定数据,可以使用 assertJsonPath 方法:

<?php

class ExampleTest extends TestCase
{
    /**
     * 一个基本的功能测试示例
     *
     * @return void
     */
    public function testBasicExample()
    {
        $response = $this->json('POST', '/user', ['name' => 'Sally']);

        $response
            ->assertStatus(201)
            ->assertJsonPath('team.owner.name', 'foo')
    }
}

测试文件上传

Illuminate\Http\UploadedFile 提供了一个 fake 方法用于生成虚拟的文件或者图像以供测试之用。它可以和 Storage facade 的 fake 方法相结合,大幅度简化了文件上传测试。举个例子,你可以结合这两者的功能非常方便地进行头像上传表单测试:

<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;

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

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

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

        // 断言文件被存储...
        Storage::disk('avatars')->assertExists($file->hashName());

        // 断言文件不存在...
        Storage::disk('avatars')->assertMissing('missing.jpg');
    }
}

虚拟文件定制

在使用 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 的实例,它提供了几个方法来方便地断言视图的内容:

public function testWelcomeView()
{
    $view = $this->view('welcome', ['name' => 'Taylor']);

    $view->assertSee('Taylor');
}

TestView 对象提供了以下断言方法:assertSeeassertSeeInOrderassertSeeTextassertSeeTextInOrderassertDontSeeassertDontSeeText

如果需要,你可以通过将 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');

支持断言

响应断言

Laravel为你的 PHPUnit 功能测试提供了各种自定义断言方法。这些断言可以在从 jsongetpostputdelete 测试方法返回的响应中访问:

assertCookie
assertCookieExpired
assertCookieNotExpired
assertCookieMissing
assertCreated
assertDontSee
assertDontSeeText
assertExactJson
assertForbidden
assertHeader
assertHeaderMissing
assertJson
assertJsonCount
assertJsonFragment
assertJsonMissing
assertJsonMissingExact
assertJsonMissingValidationErrors
assertJsonPath
assertJsonStructure
assertJsonValidationErrors
assertLocation
assertNoContent
assertNotFound
assertOk
assertPlainCookie
assertRedirect
assertSee
assertSeeInOrder
assertSeeText
assertSeeTextInOrder
assertSessionHas
assertSessionHasInput
assertSessionHasAll
assertSessionHasErrors
assertSessionHasErrorsIn
assertSessionHasNoErrors
assertSessionDoesntHaveErrors
assertSessionMissing
assertStatus
assertSuccessful
assertUnauthorized
assertViewHas
assertViewHasAll
assertViewIs
assertViewMissing

assertCookie

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

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

assertCookieExpired

断言响应包含给定的过期的 cookie:

$response->assertCookieExpired($cookieName);

assertCookieNotExpired

断言响应包含给定的永久有效的 cookie:

$response->assertCookieNotExpired($cookieName);

assertCookieMissing

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

$response->assertCookieMissing($cookieName);

assertCreated

断言做状态代码为 201 的响应:

$response->assertCreated();

assertDontSee

断言给定的字符串不包含在响应中。除非传递第二个参数 false,否则此断言将给定字符串进行转义后匹配:

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

assertDontSeeText

断言给定字符串不包含在响应文本中。除非传递第二个参数 false,否则此断言将给定字符串进行转义后匹配:

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

assertExactJson

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

$response->assertExactJson(array $data);

assertForbidden

断言响应中有禁止访问 (403) 状态码:

$response->assertForbidden();

assertHeader

断言给定的 header 在响应中存在:

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

assertHeaderMissing

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

$response->assertHeaderMissing($headerName);

assertJson

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

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

assertJsonCount

断言响应 JSON 中有一个数组,其中包含给定键的预期元素数量:

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

assertJsonFragment

断言响应包含给定 JSON 片段:

$response->assertJsonFragment(array $data);

assertJsonMissing

断言响应未包含给定的 JSON 片段:

$response->assertJsonMissing(array $data);

assertJsonMissingExact

断言响应不包含确切的 JSON 片段:

$response->assertJsonMissingExact(array $data);

assertJsonMissingValidationErrors

在 Laravel 验证返回的 json 格式的错误中缺少指定的键的时候断言:

$response->assertJsonMissingValidationErrors($keys);

assertJsonPath

断言 json 响应包含指定节点上的指定数据:

$response->assertJsonPath($path, array $data);

assertJsonStructure

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

$response->assertJsonStructure(array $structure);

assertJsonValidationErrors

在 Laravel 验证返回的 json 格式的错误中包含指定的键的时候断言:

$response->assertJsonValidationErrors(array $data);

assertLocation

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

$response->assertLocation($uri);

assertNoContent

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

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

assertNotFound

断言响应具有未找到状态码:

$response->assertNotFound();

assertOk

断言响应有 200 状态码:

$response->assertOk();

assertPlainCookie

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

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

assertRedirect

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

$response->assertRedirect($uri);

assertSee

断言给定的字符串包含在响应中。除非传递第二个参数 false ,否则此断言将给定字符串进行转义后匹配:

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

assertSeeInOrder

断言给定的字符串按顺序包含在响应中。除非传递第二个参数 false ,否则此断言将给定字符串进行转义后匹配:

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

assertSeeText

断言给定字符串包含在响应文本中。除非传递第二个参数 false,否则此断言将给定字符串进行转义后匹配:

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

assertSeeTextInOrder

断言给定的字符串按顺序包含在响应的文本中。除非传递第二个参数 false ,否则此断言将给定字符串进行转义后匹配:

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

assertSessionHas

断言 Session 包含给定的数据段:

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

assertSessionHasInput

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

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

assertSessionHasAll

断言 Session 中具有给定的值列表:

$response->assertSessionHasAll(array $data);

assertSessionHasErrors

断言 session 包含给定 $keys 的 Laravel 验证错误。如果 $keys 是关联数组,则断言 session 包含每个字段(key)的特定错误消息(value):

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

assertSessionHasErrorsIn

assertSessionHasErrors 的别名:

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

assertSessionHasNoErrors

断言 session 中没有 laravel 验证错误:

$response->assertSessionHasNoErrors();

assertSessionDoesntHaveErrors

断言 session 缺少给定的错误,如果 $key 为空,则断言 session 没有任何错误:

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

assertSessionMissing

断言 session 中缺少指定的 $key

$response->assertSessionMissing($key);

assertStatus

断言响应指定的 http 状态码:

$response->assertStatus($code);

assertSuccessful

断言响应一个成功的状态码 (>= 200 且 < 300) :

$response->assertSuccessful();

assertUnauthorized

断言一个未认证的状态码 (401):

$response->assertUnauthorized();

assertViewHas

断言为响应视图提供了一个键值对数据:

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

此外,视图数据可以作为响应上的数组变量访问:

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

assertViewHasAll

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

$response->assertViewHasAll(array $data);

assertViewIs

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

$response->assertViewIs($value);

assertViewMissing

断言视图缺少某个键:

$response->assertViewMissing($key);

身份验证断言

Laravel 还为 PHPUnit 提供了各种与身份验证相关的断言:

方法 说明
$this->assertAuthenticated($guard = null); 断言用户已通过身份验证。
$this->assertGuest($guard = null); 断言用户没有通过身份验证。
$this->assertAuthenticatedAs($user, $guard = null); 断言给定的用户已通过身份验证。
$this->assertCredentials(array $credentials, $guard = null); 断言给定的凭据有效。
$this->assertInvalidCredentials(array $credentials, $guard = null); 断言给定的凭据无效。

猜你喜欢:
暂无回复。
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册