前言
本文參考〈如何測試內含相依物件的函式〉一文,對先前〈在 Laravel 5.6 使用 Repository 與 Service Container〉一文之實作進行測試。
環境
- Windows 10
- Homestead 7.4.1
新增資源庫
在資源庫新增一個 getAllPackages() 方法,以取得資料庫的所有 Packages。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 
 | namespace App\Repositories;
 use App\Contracts\PackageInterface;
 use App\Package;
 
 class PackageRepository implements PackageInterface
 {
 protected $package;
 
 public function __construct(Package $package)
 {
 $this->package = $package;
 }
 
 public function getAllPackages()
 {
 $packages = $this->package->all();
 
 return $packages;
 }
 }
 
 | 
新增控制器
在 PackageController 新增 getAllPackages() 方法。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 
 | namespace App\Http\Controllers;
 use App\Contracts\PackageInterface;
 
 class PackageController extends Controller
 {
 protected $package;
 
 public function __construct(PackageInterface $package)
 {
 $this->package = $package;
 }
 
 public function index()
 {
 $packages = $this->package->getAllPackages();
 
 return view('package.index', compact('packages'));
 }
 }
 
 | 
測試
編輯 tests\TestCase.php 檔。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 
 | namespace Tests;
 use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
 use Mockery;
 
 abstract class TestCase extends BaseTestCase
 {
 use CreatesApplication;
 
 public function initMock($class)
 {
 
 $mock = Mockery::mock($class);
 
 
 $this->app->instance($class, $mock);
 
 return $mock;
 }
 }
 
 | 
在 tests\Feature 新增 PackageControllerTest.php 檔。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 
 | namespace Tests\Feature;
 use Tests\TestCase;
 use App\Contracts\PackageInterface;
 use App\Http\Controllers\PackageController;
 use Illuminate\Database\Eloquent\Collection;
 use Mockery;
 
 class PackageControllerTest extends TestCase
 {
 
 protected $mock;
 
 
 protected $target;
 
 public function setUp()
 {
 parent::setUp();
 
 
 $this->mock = $this->initMock(PackageInterface::class);
 
 
 $this->target = $this->app->make(PackageController::class);
 }
 
 public function testIndex()
 {
 
 $expected = new Collection([
 ['name' => 'Name 1', 'html_url' => 'HTML URL 1'],
 ['name' => 'Name 2', 'html_url' => 'HTML URL 2'],
 ['name' => 'Name 3', 'html_url' => 'HTML URL 3'],
 ]);
 
 
 $this->mock
 ->shouldReceive('getAllPackages')
 ->once()
 ->andReturn($expected);
 
 
 $actual = $this->target->index()->packages;
 
 
 $this->assertEquals($expected, $actual);
 }
 
 public function tearDown()
 {
 
 $this->mock = null;
 $this->target = null;
 }
 }
 
 | 
單元測試的 3A 原則
Arrange
準備測試資料 $fake、mock 物件 $mock、待測物件 $target,與建立測試期望値 $expected。
Act
執行待測物件的 method,與建立實際結果値 $actual。
Assert
使用 PHPUnit 的斷言函式測試 $expected 與 $actual 是否如預期。