Laravel5とMockeryの覚書
こういうコントローラーがあって
CustomerController.php
<?php namespace App\Http\Controllers;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use App\Customer;
use Illuminate\Http\Request;
class CustomerController extends Controller {
protected $customer;
public function __construct(Customer $customer)
{
$this->customer = $customer;
}
/**
* Display a listing of the resource.
*
* @return Response
*/
public function getIndex()
{
$customers = $this->customer->all()->sortByDesc('id');
return view('customer.index')->with(compact('customers'));
}
}
こういうテストがあるとして
それぞれの説明を書きとめ
customerTest.php
<?php
use App\Customer;
class CustomerTest extends TestCase {
protected $customerMock;
public function setUp()
{
parent::setUp();
$this->customerMock = Mockery::mock('App\Customer');
}
public function tearDown()
{
parent::tearDown();
Mockery::close();
}
public function testIndex()
{
$this->customerMock
->shouldReceive('all')
->once()
->andReturn($this->customerMock);
$this->app->instance('App\Customer', $this->customerMock);
$this->call('GET', '/customers/');
}
}
モックの用意
setUpメソッドでモックのインスタンスを作成する
注意点としてはモックに渡すモデル名は完全な名前空間付きにする
protected $customerMock;
public function setUp()
{
parent::setUp();
$this->customerMock = Mockery::mock('App\Customer');
}
モックのクローズ
これは必須
public function tearDown()
{
parent::tearDown();
Mockery::close();
}
モデルの"all"メソッドが呼ばれることをテスト
public function testIndex()
{
$this->customerMock
->shouldReceive('all')
->once()
->andReturn($this->customerMock);
$this->app->instance('App\Customer', $this->customerMock);
$this->call('GET', '/customers/');
}
shouldReceiveとonce
これがテストの本体(?)でControllerでall()が呼ばれないとテストが落ちる
注意点としては上で書いた
Mockery::close()
を呼んでおかないとテスト自体が実行されない。(はまった)
->shouldReceive('all')
->once()
andReturn
この例で言うとallが呼ばれた時に返す値(そのまんまだけど)
このコントローラーではall()の後にsortByDesc()を呼んでいるので自身を返さないといけないので
以下のようにする
->andReturn($this->customerMock);
モックの注入
これはLaravelの機能で自動的にモデルが注入される前に差し替えている(んだと思う)
ここでもクラス名は完全な名前空間付きにする
$this->app->instance('App\Customer', $this->customerMock);