Laravel — Testing — HTTP Tests (官方文件原子化翻譯筆記)
By: Ray Lee
Tags: Test, Backend, Laravel, Documentation

Photo by Scott Graham on Unsplash

# 版本

Laravel 8.x

# 前言

我喜歡使用 Laravel 開發的感覺, 除了開發快速, 程式碼簡潔且優雅之外, Laravel 框架本身也是一個很好的學習參照物。 本篇主要將官方文件重點整理成 Q&A 的形式呈現, 原子化的概念, 這方式並不適用於每個人, 但若對你有幫助, 我會很開心。

# Introduction

以下的 Laravel example code 的意思是？

Example:

<?php



namespace Tests\Feature;



use Illuminate\Foundation\Testing\RefreshDatabase;

use Illuminate\Foundation\Testing\WithoutMiddleware;

use Tests\TestCase;



class ExampleTest extends TestCase

{

public function testBasicTest()

{

$response = $this->get('/');



$response->assertStatus(200);

}

}

Answer: 如果對 ‘/’ 發 request, response 將會是 200, 如果不是則測試不通過

# Customizing Request Headers

以下的 Laravel example code 的意思是？

Example:

<?php



class ExampleTest extends TestCase

{

public function testBasicExample()

{

$response = $this->withHeaders([

'X-Header' => 'Value',

])->json('POST', '/user', ['name' => 'Sally']);



$response

->assertStatus(201)

->assertJson([

'created' => true,

]);

}

}

Answer: 自訂 request 的 header, 然後以 POST 的方式帶著參數發到 ‘/user’ url 並斷言需以 JSON 格式回傳 ‘created’ => true, status code 為 201

Laravel Testing 中, CSRF token 會運作嗎？

不會

# Cookies

以下的 Laravel example code 的意思是？

Example:

<?php



class ExampleTest extends TestCase

{

public function testCookies()

{

$response = $this->withCookie('color', 'blue')->get('/');



$response = $this->withCookies([

'color' => 'blue',

'name' => 'Taylor',

])->get('/');

}

}

Answer: 建立一個 test case, 定義 cookie 為 ‘color’ => ‘blue’, 並向 ‘/’ 發 GET request, 上面兩種定義 cookie 的方式皆可

# Debugging Responses

以下的 Laravel example code 的意思是？

Example:

<?php



namespace Tests\Feature;



use Illuminate\Foundation\Testing\RefreshDatabase;

use Illuminate\Foundation\Testing\WithoutMiddleware;

use Tests\TestCase;



class ExampleTest extends TestCase

{

public function testBasicTest()

{

$response = $this->get('/');



$response->dumpHeaders();



$response->dumpSession();



$response->dump();

}

}

Answer: 對 ‘/’ 發 GET request, 並印出 headers, session, 以及整個 response 方便 debug

# Session / Authentication

以下的 Laravel Testing example code 的意思是？

Example:

<?php



class ExampleTest extends TestCase

{

public function testApplication()

{

$response = $this->withSession(['foo' => 'bar'])

->get('/');

}

}

Answer: 定義 session 載入檔案 [‘foo’ => ‘bar’], 並發送 ‘/’ GET request

以下的 Laravel example code 的意思是？

Example:

<?php

use App\Models\User;



class ExampleTest extends TestCase

{

public function testApplication()

{

$user = User::factory()->create();



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

->withSession(['foo' => 'bar'])

->get('/');

}

}

Answer: 建立一個 user, 並指定由這個 user 登入, 使用 ‘api’ guard 來驗證身份 (也可不設), 並帶著 session [‘foo’ => ‘bar’], 發送 ‘/’ GET request

# Testing JSON APIs

以下的 Laravel example code 的意思是？

Example:

<?php



class ExampleTest extends TestCase

{

public function testBasicExample()

{

$response = $this->postJson('/user', ['name' => 'Sally']);



$response

->assertStatus(201)

->assertJson([

'created' => true,

]);

}

}

Answer: 使用 JSON 格式發送 POST request, 發送位址為 ‘/user’, body 為 [‘name’ => ‘Sally’] 並斷言回傳 status code 201, 以及 JSON “created” : “true”

以下的 Laravel example code 的意思是？

Example:

<?php



class ExampleTest extends TestCase

{

public function testBasicExample()

{

$response = $this->postJson('/user', ['name' => 'Sally']);



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

}

}

Answer: 使用 JSON 格式發送 POST request, 發送位址為 '/user' , body 為 ['name' => 'Sally'] 並斷言回傳 的 JSON response 的 'created' value 為 true

# Verifying An Exact JSON Match

以下的 Laravel example code 的意思是？

Example:

<?php

class ExampleTest extends TestCase

{

public function testBasicExample()

{

$response = $this->json('POST', '/user', ['name' => 'Sally']);



$response

->assertStatus(201)

->assertExactJson([

'created' => true,

]);

}

}

Answer: 使用 JSON 格式發送 POST request, 發送位址為 '/user' , body 為 ['name' => 'Sally'] 並斷言 response 會是 JSON ['created => true] , 若不是則 test fail

# Verifying JSON Paths

以下的 Laravel example code 的意思是？

Example:

<?php



class ExampleTest extends TestCase

{

public function testBasicExample()

{

$response = $this->json('POST', '/user', ['name' => 'Sally']);



$response

->assertStatus(201)

->assertJsonPath('team.owner.name', 'foo');

}

}

Answer: 使用 JSON 格式發送 POST request, 發送位址為 '/user' , body 為 ['name' => 'Sally'] 並斷言 response 需包含 status code 201, 以及在 'team.owner.name' 的路徑, value 需為 'foo'

# Testing File Uploads

以下的 Laravel example code 的意思是？

Example:

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

}

}

Answer:

<?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()

{

// fake 一個 storage disk 名為 'avatars'

Storage::fake('avatars');



// fake 一個 image 名為 'avatar.jpg', 並 assign 到 $file

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



// 對 '/avatar' 發起一個 JSON POST Request, 帶著 ['avatar' => $file]

$response = $this->json('POST', '/avatar', [

'avatar' => $file,

]);



// 斷言在 'avatars' 這個 storage disk 中, 有 $file 的 hash name, 若無則 test fails

Storage::disk('avatars')->assertExists($file->hashName());



// 斷言在 'avatars' 這個 storage disk 中, 沒有 'missing.jpg' 這個檔案, 若有則 test fails

Storage::disk('avatars')->assertMissing('missing.jpg');

}

}

# Fake File Customization

以下的 Laravel example code 的意思是？

Example:

<?php



class ExampleTest extends TestCase

{

public function testBasicExample()

{

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

}

}

Answer: fake 一個 image, 名為 'avatar.jpg' , 定義 width, height, 以及 size

以下的 Laravel example code 的意思是？

Example:

<?php



class ExampleTest extends TestCase

{

public function testBasicExample()

{

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

}

}

Answer: 使用 faker 的 create method 建立一個 PDF file, 可以指定 size 以及 mimeType (optional)

# Testing Views

以下的 Laravel example code 的意思是？

Example:

<?php



class ExampleTest extends TestCase

{

public function testWelcomeView()

{

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



$view->assertSee('Taylor');

}

}

Answer: test 的 view method 會 return 一個 Illuminate\Testing\TestView instance, 可帶入 view name 以及 parameters, TestView instance 也提供了很多 assertion method: assertsee , assertSeeInOrder , assertSeeText , assertSeeTextInOrder , assertDontSee , assertDontSeeText

以下的 Laravel example code 的意思是？

Example:

<?php



class ExampleTest extends TestCase

{

public function testWelcomeView()

{

$contents = (string) $this->view('welcome');

}

}

Answer: 若有需要, 也可取得 raw, rendered view 的內容

# Sharing Errors

以下的 Laravel example code 的意思是？

Example:

<?php



class ExampleTest extends TestCase

{

public function testWelcomeView()

{

$view = $this->withViewErrors([

'name' => ['Please provide a valid name.']

])->view('form');



$view->assertSee('Please provide a valid name.');

}

}

Answer: 將模擬的 error message 'name' => ['Please provide a valid name.'] 待到指定的 view 'form'

# Rendering Blade & Components

以下的 Laravel Test example code 的意思是？

Example:

<?php

$view = $this->blade(

'<x-component :name="$name" />',

['name' => 'Taylor']

);



$view->assertSee('Taylor');

Answer: 使用 blade() arg1 定義使用名為 component 的 component, 且定義帶入的參數為 $name arg2 定義 $name 為 'Taylor' 最後斷言 $view 需可看到 'Taylor'

以下的 Laravel Test example code 的意思是？

Example:

<?php

$view = $this->component(Profile::class, ['name' => 'Taylor']);



$view->assertSee('Taylor');

Answer: 使用 component() arg1 使用的 component class arg2 定義帶入的 args key/value 最後斷言 $view 需可看到 'Taylor'

# Available Assertions

# Response Assertions

# assertCookie

以下的 Laravel Test example code 的意思是？

Example:

<?php

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

Answer: 斷言 response 帶有指定 $cookie

# assertCookieExpired

以下的 Laravel Test example code 的意思是？

Example:

<?php

$response->assertCookieExpired($cookieName);

Answer: 斷言 response 帶有指定 $cookie, 且該 cookie 已過期

# assertCookieNotExpired

以下的 Laravel Test example code 的意思是？

Example:

<?php

$response->assertCookieNotExpired($cookieName);

Answer: 斷言 response 帶有指定 $cookie, 且該 cookie 還沒過期

# assertCookieMissing

以下的 Laravel Test example code 的意思是？

Example:

<?php

$response->assertCookieMissing($cookieName);

Answer: 斷言 response 未帶有指定 cookie

# assertCreated

以下的 Laravel Test example code 的意思是？

Example:

<?php

$response->assertCreated();

Answer: 斷言 response status code 為 201

# assertDontSee

以下的 Laravel Test example code 的意思是？

Example:

<?php

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

Answer: 斷言 response 含有指定 $value string 預設會自動 escape string, 除非 arg2 為 false

# assertDontSeeText

以下的 Laravel Test example code 的意思是？

Example:

<?php

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

Answer: 斷言 response text 中含有指定 $value string 預設會自動 escape string, 除非 arg2 為 false 在跑此 assertion 之前, 會先把 response 的內容用 PHP function strip_tags 跑過

# assertExactJson

以下的 Laravel Test example code 的意思是？

Example:

<?php

$response->assertExactJson(array $data);

Answer: 斷言 response 中, 含有完全符合指定 $data 的 JSON data

# assertForbidden

以下的 Laravel Test example code 的意思是？

Example:

<?php

$response->assertForbidden();

Answer: 斷言 response 含有 HTTP status code 403

# assertHeader

以下的 Laravel Test example code 的意思是？

Example:

<?php

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

Answer: 斷言 response 含有指定的 header 以及其 value

# assertHeaderMissing

以下的 Laravel Test example code 的意思是？

Example:

<?php

$response->assertHeaderMissing($headerName);

Answer: 斷言 response 不含有指定 header

# assertJson

以下的 Laravel Test example code 的意思是？

Example:

<?php

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

Answer: 斷言 response 含有指定 JSON data assertJson 會將 response 轉成 array, 並且使用 PHPUnit::assertArraySubset 確認指定的 array 存在於 JSON response, 所以如果該 JSON response 中有其他 property, test 也會 pass 過去

# assertJsonCount

以下的 Laravel Test example code 的意思是？

Example:

<?php

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

Answer: 斷言 response JSON 中, 指定的 $key 為 array, 而裡頭的 item 數量跟斷言的 $count 數量相符

# assertJsonFragment

以下的 Laravel Test example code 的意思是？

Example:

<?php

Route::get('/users', function () {

return [

'users' => [

[

'name' => 'Taylor Otwell',

],

],

];

});



$response->assertJsonFragment(['name' => 'Taylor Otwell']);

Answer: 斷言 response 中, 在某個位置有著 ['name' => 'Taylor Otwell'

# assertJsonMissing

以下的 Laravel Test example code 的意思是？

Example:

<?php

$response->assertJsonMissing(array $data);

Answer: 斷言 response 中, 並無 JSON $data 假如 Response 為 ['a' => 1, 'b' => 2] , 那如果 $data 為 ['a' => 2, 'b' => 2] , 這樣也算 fail

# assertJsonMissingExact

以下的 Laravel Test example code 的意思是？

Example:

<?php

$response->assertJsonMissingExact(array $data);

Answer: 斷言 response 中, 並無 JSON $data 假如 Response 為 ['a' => 1, 'b' => 2] , 那如果 $data 為 ['a' => 2, 'b' => 2] , 因為沒有完全符合, 這樣便不算 fail, 然而測試結果為 not perform any assertion , 不確定這樣的行為是否正常, 預期行為應為 pass

# assertJsonMissingValidationErrors

以下的 Laravel Test example code 的意思是？

Example:

<?php

$response->assertJsonMissingValidationErrors($keys);

Answer: 斷言 response 中, 並無指定 $key 的 JSON validation error

# assertJsonPath

以下的 Laravel Test example code 的意思是？

Example:

<?php

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

Answer : 斷言 response 在指定的 $path 位置含有指定的 $data 見範例如下:

: 斷言 response 在指定的 $path 位置含有指定的 $data 見範例如下: Demonstration:

<?php

// response

{

"user": {

"name": "Steve Schoger"

}

}



// test method

$response->assertJsonPath('user.name', 'Steve Schoger');

# assertJsonStructure

以下的 Laravel Test example code 的意思是？

Example:

<?php

$response->assertJsonStructure(array $structure);

Answer : 斷言 response 為定義的 JSON 結構 見範例如下:

: 斷言 response 為定義的 JSON 結構 見範例如下: Demonstration:

<?php

// response

{

"user": {

"name": "Steve Schoger"

}

}



// test method

$response->assertJsonStructure([

'user' => [

'name',

]

]);

# assertJsonValidationErrors

以下的 Laravel Test example code 的意思是？

Example:

<?php

$response->assertJsonValidationErrors(array $data);

Answer: 斷言 response 需含有指定 keys 的 errors, 適用於 validator error 是以 JSON 結構回傳, 而不是置於 session 當中

# assertLocation

以下的 Laravel Test example code 的意思是？

Example:

<?php

$response->assertLocation($uri);

Answer: 斷言 response 的 Location header 的 value 為 $uri

# assertNoContent

以下的 Laravel Test example code 的意思是？

Example:

<?php

$response->assertNoContent($status = 204)

Answer: 斷言 response 需為 no content, 且 status code 為 204

# assertNotFound

以下的 Laravel Test example code 的意思是？

Example:

<?php

$response->assertNotFound();

Answer: 斷言 response status code 需為 404

# assertOk

以下的 Laravel Test example code 的意思是？

Example:

<?php

$response->assertOk()

Answer: 斷言 response status code 需為 200

# assertPlainCookie

以下的 Laravel Test example code 的意思是？

Example:

<?php

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

Answer: 斷言 response 含有指定的 unencrypted cookie

# assertRedirect

以下的 Laravel Test example code 的意思是？

Example:

<?php

$response->assertRedirect($uri);

Answer: 斷言 response 為 redirect 到 $uri

# assertSee

以下的 Laravel Test example code 的意思是？

Example:

<?php

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

Answer: 斷言 response 含有 string $value, 預設會 escape 此 string, 可指定為 false

# assertSeeInOrder

以下的 Laravel Test example code 的意思是？

Example:

<?php

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

Answer: 斷言 response 中, string 的順序如 $values 的定義, 預設 escape, 可變更為 false

# assertSeeText

以下的 Laravel Test example code 的意思是？

Example:

<?php

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

Answer: 斷言 response text 中有 string $value, 預設會 escape string, 可改為 false response 內容會先經過 strip_tags 處理過, 才會到 assertion

# assertSeeTextInOrder

以下的 Laravel Test example code 的意思是？

Example:

<?php

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

Answer: 斷言 response text 中有 string $value, 並且照定義的順序排列, 預設會 escape string, 可改為 false response 內容會先經過 strip_tags 處理過, 才會到 assertion

# assertSessionHas

以下的 Laravel Test example code 的意思是？

Example:

<?php

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

Answer: 斷言 session $key 含有 $value

# assertSessionHasInput

以下的 Laravel Test example code 的意思是？

Example:

<?php

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

Answer: 斷言 session 在 flashed input array 含有指定的 key / value

# assertSessionHasAll

以下的 Laravel Test example code 的意思是？

Example:

<?php

$response->assertSessionHasAll(array $data);

Answer : 斷言 session 在 含有指定的 array [key / value] 例如 session 含有 name 及 status key, 可定義如下：

: 斷言 session 在 含有指定的 array [key / value] 例如 session 含有 及 key, 可定義如下： Demonstration:

<?php

$response->assertSessionHasAll([

'name' => 'Taylor Otwell',

'status' => 'active',

]);

# assertSessionHasErrors

以下的 Laravel Test example code 的意思是？

Example:

<?php

$response->assertSessionHasErrors(

array $keys, $format = null, $errorBag = 'default'

);

Answer : 斷言 session 中含有指定的 errors, 可以只斷言 key, 也可 key / value 這個適合用來測試會將 error 放入 session 的 route, 而不是將 error 導出 JSON response 的 route 例如, 斷言 session 中有 error message filed name , email (demonstration 1) 也可指定 error message key / value (demonstration 2)

: 斷言 session 中含有指定的 errors, 可以只斷言 key, 也可 key / value 這個適合用來測試會將 error 放入 session 的 route, 而不是將 error 導出 JSON response 的 route 例如, 斷言 session 中有 error message filed , (demonstration 1) 也可指定 error message (demonstration 2) Demonstration1:

<?php

$response->assertSessionHasErrors(['name', 'email']);

Demonstration2:

<?php

$response->assertSessionHasErrors([

'name' => 'The given name was invalid.'

]);

# assertSessionHasErrorsIn

以下的 Laravel Test example code 的意思是？

Example:

<?php

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

Answer: 斷言 session 中, messageBag $errorBag 中含有指定的 error / message $keys , 可定義 key 以及 key / value

# assertSessionHasNoErrors

以下的 Laravel Test example code 的意思是？

Example:

<?php

$response->assertSessionHasNoErrors();

Answer: 斷言 session 中沒有 validation errors

# assertSessionDoesntHaveErrors

以下的 Laravel Test example code 的意思是？

Example:

<?php

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

Answer: 斷言 session 中沒有指定的 error key

# assertSessionMissing

以下的 Laravel Test example code 的意思是？

Example:

<?php

$response->assertSessionMissing($key);

Answer: 斷言 session 中沒有指定的 $key

# assertStatus

以下的 Laravel Test example code 的意思是？

Example:

<?php

$response->assertStatus($code);

Answer: 斷言 response 的 status code 為 $code

# assertSuccessful

以下的 Laravel Test example code 的意思是？

Example:

<?php

$response->assertSuccessful();

Answer: 斷言 response 的 status code 為 (>= 200 and < 300)

# assertUnauthorized

以下的 Laravel Test example code 的意思是？

Example:

<?php

$response->assertUnauthorized();

Answer: 斷言 response 的 status code 為 401

# assertViewHasAll

以下的 Laravel Test example code 的意思是？

Example:

<?php

$response->assertViewHasAll(array $data);

Answer:

<?php

// 斷言 response view 中含有指定的 keys 或是多組 key / value

$rseponse->assertViewHasAll([

'name',

'email',

]);



$rseponse->assertViewHasAll([

'name' => 'Taylor Otwell',

'email' => 'taylor@example.com,',

]);

# assertViewIs

以下的 Laravel Test example code 的意思是？

Example:

<?php

$response->assertViewIs($value);

Answer: 斷言 response view name 跟 $value 一樣

# assertViewMissing

以下的 Laravel Test example code 的意思是？

Example:

<?php

$response->assertViewMissing($key);

Answer: 斷言 response view 中沒有 $key

# Authentication Assertions

# assertAuthenticated

以下的 Laravel Test example code 的意思是？

Example:

<?php

$this->assertAuthenticated($guard = null);

Answer: 斷言 user is authenticated

# assertGuest

以下的 Laravel Test example code 的意思是？

Example:

<?php

$this->assertGuest($guard = null);

Answer: 斷言 user is not authenticated

# assertAuthenticatedAs

以下的 Laravel Test example code 的意思是？

Example:

<?php

$this->assertAuthenticatedAs($user, $guard = null);