Help us understand the problem. What is going on with this article?

MockeryでLaravel5のコントローラーテストの基本覚書

More than 1 year has passed since last update.

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);
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした