HTTP 测试


HTTP Tests

简介

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

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

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\User;
    class ExampleTest extends TestCase{ 
       public function testApplication()  
         {     
            $user = factory(User::class)->create();        
            $response = $this->actingAs($user)                 
                    ->withSession(['foo' => 'bar'])                        
                    ->get('/');  
          }
     }

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

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

测试 JSON APIs

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

<?php
    class ExampleTest extends TestCase{   
     /**
     * 一个简单的功能测试用例。
     *
     * @return void
     */   
     public function testBasicExample() 
        {    
            $response = $this->json('POST', '/user', ['name' => 'Sally']);     
            $response        
                ->assertStatus(201)            
                ->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(201)            
              ->assertExactJson([           
                   'created' => true,           
                  ]);  
         }
     }

测试文件上传

IlluminateHttpUploadedFile 提供了一个 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');        
              $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);

可用断言

响应断言

Laravel 给 PHPUnit 测试提供了各种各样的常用断言方法。可从 json, get, post, put,和 delete 测试方法中访问这些断言:

assertCookie

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

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

assertCookieExpired

断言响应中包含了给定的 cookie 且它已过期:

$response->assertCookieExpired($cookieName);

assertCookieNotExpired

断言响应中包含了给定的 cookie 且它未过期:

$response->assertCookieNotExpired($cookieName);

assertCookieMissing

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

$response->assertCookieMissing($cookieName);

assertDontSee

断言响应中不包含给定的字符串:

$response->assertDontSee($value);

assertDontSeeText

断言给定字符串不包含在响应文本中:

$response->assertDontSeeText($value);

assertExactJson

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

$response->assertExactJson(array $data);

assertForbidden

断言响应中有禁止状态码:

$response->assertForbidden();

assertHeader

断言响应中有给定的包头:

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

assertHeaderMissing

断言响应中没有给定的报头:

$response->assertHeaderMissing($headerName);

assertJson

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

$response->assertJson(array $data);

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

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

$response->assertJsonMissingValidationErrors($keys);

assertJsonStructure

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

$response->assertJsonStructure(array $structure);

assertJsonValidationErrors

断言响应具有给定键的给定 JSON 验证错误:

$response->assertJsonValidationErrors($keys);

assertLocation

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

$response->assertLocation($uri);

assertNotFound

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

$response->assertNotFound();

assertOk

断言响应有 200 状态码:

$response->assertOk();

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(array $data);

assertSessionHasErrors

断言 session 中包含一个给定字段的错误:

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

assertSessionHasErrorsIn

断言 session 中具有给定的错误:

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

assertSessionHasNoErrors

断言 session 没有错误:

$response->assertSessionHasNoErrors();

assertSessionDoesntHaveErrors

断言 session 没有给定键错误:

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

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);

Authentication Assertions

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

MethodDescription
$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 网站上。