HTTP 测试

未匹配的标注

HTTP Tests

介绍

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

断言响应中包含给定的 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, $strict = false);

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); 断言给定的凭据无效。

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

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
上一篇 下一篇
Summer
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
贡献者:5
讨论数量: 0
发起讨论 只看当前版本


暂无话题~