HTTP 测试

优质
小牛编辑
128浏览
2023-12-01

简介

Laravel 为 HTTP 请求的生成和输出的检查都提供了非常流畅的 API。例如,你可以查看下面的这个测试用例:

<?php

namespace Tests\Feature;

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

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(200)
            ->assertJson([
                'created' => true,
            ]);
    }
}

{tip} 运行测试时,CSRF 中间件会自动禁用。

Session / 认证

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

<?php

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

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

<?php

use App\User;

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

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

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

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

测试 JSON API

Laravel 也提供了几个辅助函数来测试JSON API 和它们的相应。例如 json, get, post, put, patchdelete 可以被用于发送各种 HTTP 动作。你也可以轻松地将数据和请求头传递到这些方法中。让我们写一个 POST 请求到 /user 并断言返回期望的数据来开始使用它们:

<?php

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

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

{tip} assertJson 方法将响应转换为数组并且利用 PHPUnit::assertArraySubset 来验证给定的数组存在于应用返回的 JSON 响应中。所以,如果 JSON 相应中如果有其他属性,测试仍旧会在给定数组存在的情况下通过。

验证完全匹配

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

<?php

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

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

测试文件上传

进行测试时,这个 Illuminate\Http\UploadedFile 类提供了一个可能用来生成虚拟的文件或者图片的 fake 方法。它与这个 Storage Facade 的 fake 方法结合在一起巨大的简化了文件上传的测试。 例如 , 你可能把那两个特征结合起来很容易测试一个头像的上传成功:

<?php

namespace Tests\Feature;

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

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

        $response = $this->json('POST', '/avatar', [
            'avatar' => UploadedFile::fake()->image('avatar.jpg')
        ]);

        // 验证文件已存储 ...
        Storage::disk('avatars')->assertExists('avatar.jpg');

        // 验证一个文件不存在 ...
        Storage::disk('avatars')->assertMissing('missing.jpg');
    }
}

虚拟文件定义

当使用这个 fake 方法创建文件时,为了更好地测试你想要的图片尺寸,你也许会设定图片的宽度,高度,以及图片的大小 :

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

此外,在进行创建图片时,你可能使用这个 create 方法创建其它任何类型的文件:

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

可用断言

响应断言

Laravel 为您的 PHPUnit 测试提供了各种常规断言方法。 这些断言可以通过从 json, get, post, put, 和 delete 测试方法返回的响应来访问:

assertCookie assertCookieExpired assertCookieMissing assertDontSee assertDontSeeText assertExactJson assertHeader assertHeaderMissing assertJson assertJsonFragment assertJsonMissing assertJsonMissingExact assertJsonStructure assertJsonValidationErrors assertPlainCookie assertRedirect assertSee assertSeeInOrder assertSeeText assertSeeTextInOrder assertSessionHas assertSessionHasAll assertSessionHasErrors assertSessionHasErrorsIn assertSessionMissing assertStatus assertSuccessful assertViewHas assertViewHasAll assertViewIs assertViewMissing

断言 Cookie

断言此响应包含给定的 cookie

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

断言 Cookie 过期

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

$response->assertCookieExpired($cookieName);

断言 Cookie 丢失

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

$response->assertCookieMissing($cookieName);

assertDontSee

验证所给的字符串不包含在响应中:

$response->assertDontSee($value);

assertDontSeeText

验证所给的字符串不包含在响应的文本中:

$response->assertDontSeeText($value);

assertExactJson

验证响应和所给 JSON 数据完全符合:

$response->assertExactJson(array $data);

assertHeader

验证所给的头目前在响应中:

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

assertHeaderMissing

验证所给的头目前没有在响应中:

$response->assertHeaderMissing($headerName);

assertJson

验证响应包含所给的 JSON 数据:

$response->assertJson(array $data);

assertJsonFragment

验证此响应包含给定的 JSON 片段:

$response->assertJsonFragment(array $data);

assertJsonMissing

验证此响应不包含给定的 JSON 片段:

$response->assertJsonMissing(array $data);

assertJsonMissingExact

验证此响应不包含确切的 JSON 片段

$response->assertJsonMissingExact(array $data);

assertJsonStructure

验证此响应含有给定的 JSON 结构:

$response->assertJsonStructure(array $structure);

assertJsonValidationErrors

验证此响应有给定键的 JSON 验证错误 :

$response->assertJsonValidationErrors($keys);

assertPlainCookie

验证此响应包含所给的 cookie 『 加密 』:

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

assertRedirect

断言响应重定向到指定 URI:

$response->assertRedirect($uri);

assertSee

断言响应中包含指定字符串:

$response->assertSee($value);

assertSeeInOrder

断言响应中有序包含指定字符串:

$response->assertSeeInOrder(array $values);

assertSeeText

断言响应文本中包含指定字符串:

$response->assertSeeText($value);

assertSeeTextInOrder

断言响应文本中有序包含指定字符串:

$response->assertSeeTextInOrder(array $values);

assertSessionHas

断言 session 包含数据片段:

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

assertSessionHasAll

断言 session 中存在指定的所有值:

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

assertSessionHasErrors

断言 session 中含有指定错误:

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

assertSessionHasErrorsIn

断言 session 中含有指定错误:

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

assertSessionMissing

断言 session 中不含有指定键:

$response->assertSessionMissing($key);

assertStatus

断言响应中存在指定状态码:

$response->assertStatus($code);

assertSuccessful

断言响应中存在成功状态码:

$response->assertSuccessful();

assertViewHas

断言响应视图中存在指定数据片段:

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

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