HTTP 测试
简介
Laravel 为生成 HTTP 请求、测试输出提供了流式 API。举个例子,我们 Laravel 提供的测试示例:
<?php
namespace Tests\Feature;
use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithoutMiddleware;
class ExampleTest extends TestCase
{
/**
* A basic test example.
*
* @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' => 'LaravelAcademy',
])->json('POST', '/user', ['name' => '学院君']);
$response
->assertStatus(200)
->assertJson([
'created' => true,
]);
}
}
注:运行测试时,CSRF 中间件会自动被禁止。
会话/认证
Laravel 提供了多个辅助函数用于在 HTTP 测试期间处理会话(Session),首先,你可以使用 withSession
方法来设置会话数据。这对于在发起请求之前加载会话数据很有用:
<?php
class ExampleTest extends TestCase
{
public function testApplication()
{
$response = $this->withSession(['foo' => 'bar'])
->get('/');
}
}
当然,会话最常见的用途还是维护认证用户的状态。对此,辅助函数 actionAs
方法提供了一个简单的方式来认证当前用户,例如,我们可以使用模型工厂来生成并认证用户:
<?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 名作为 actionAs
方法的第二个参数来指定使用哪一个 guard 来认证给定用户:
$this->actingAs($user, 'api');
测试 JSON API
Laravel 还提供了多个辅助函数用于测试 JSON API 及其响应。例如,json
、get
、post
、put
、patch
和 delete
方法用于通过多种 HTTP 请求方式发出请求。你还可以轻松传递数据和请求头到这些方法。作为开始,我们编写测试来生成 POST
请求到 /user
并断言返回的数据是否是我们所期望的:
<?php
class ExampleTest extends TestCase
{
/**
* 基本功能测试示例.
*
* @return void
*/
public function testBasicExample()
{
$response = $this->json('POST', '/user', ['name' => '学院君']);
$response
->assertStatus(200)
->assertJson([
'created' => true,
]);
}
}
注:assertJson
方法将响应转化为数组并使用PHPUnit::assertArraySubset
验证给定数组在应用返回的 JSON 响应中是否存在。所以,如果在 JSON 响应中存在其它属性,这个测试仍然会通过,只要给定的片段存在即可。
验证完全匹配
如果你想要验证给定数组和应用返回的 JSON 能够完全匹配,可以使用 assertExactJson
方法:
<?php
class ExampleTest extends TestCase
{
/**
* A basic functional test example.
*
* @return void
*/
public function testBasicExample()
{
$response = $this->json('POST', '/user', ['name' => '学院君']);
$response
->assertStatus(200)
->assertExactJson([
'created' => true,
]);
}
}
测试文件上传
Illuminate\Http\UploadedFile
类提供了一个 fake
方法用于生成假文件或图片进行测试。这一机制和 Storage
门面的 fake
方法联合在一起,极大地简化了文件上传的测试。例如,你可以联合这两个特性来轻松测试头像上传表单:
<?php
namespace Tests\Feature;
use Tests\TestCase;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class ExampleTest extends TestCase
{
public function testAvatarUpload()
{
Storage::fake('avatars');
$response = $this->json('POST', '/avatar', [
'avatar' => UploadedFile::fake()->image('avatar.jpg')
]);
// Assert the file was stored...
Storage::disk('avatars')->assertExists('avatar.jpg');
// Assert a file does not exist...
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
断言响应包含给定 Cookie:
$response->assertCookie($cookieName, $value = null);
assertCookieExpired
断言响应包含给定 Cookie 并且已过期:
$response->assertCookieExpired($cookieName);
assertCookieMissing
断言响应不包含给定 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
断言会话中包含给定数据片段:
$response->assertSessionHas($key, $value = null);
assertSessionHasAll
断言会话中存在给定值列表:
$response->assertSessionHasAll($key, $value = null);
assertSessionHasErrors
断言会话中包含给定字段的错误信息:
$response->assertSessionHasErrors(array $keys, $format = null, $errorBag = 'default');
assertSessionHasErrorsIn
断言会话中包含给定错误:
$response->assertSessionHasErrorsIn($errorBag, $keys = [], $format = null);
assertSessionMissing
断言会话中不包含给定键:
$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); |
断言给定认证信息无效 |
9 Comments
测试文件上传时,保存目录和判断目录不一致如何解决啊。
怎么会 你保存目录和判断目录分别是怎么样的
test 检查地址在这个framework下面,保存的在app 下面
保存在了
public/images
目录下,你测试的是public
目录?怎么测试public,我看了那个方法,如果传至了就去 framework/testing/disks/ 这个下面找,不传值就用默认的啊,我怎么指定目录呢?