
目次
背景
こんにちは。 かりんとうマニア(@karintozuki)です。
皆さん、テスト書いてますか?テストを書く上でMockは欠かせないですよね。
LaravelではMockを作る方法がいくつかあります。私が働いているプロジェクトでは色々な書き方が混在していたので、それらを整理する意味でもここにMockの方法をまとめていきます。
この記事では、LaravelでMockを使用するさまざまな方法を紹介していきます。
コードサンプル内ではService
という仮のクラスのrun()
関数をモックする例を通じて紹介します。
1. mock関数を使う
mock関数を使ったインスタンスの置き換え
以下の例はmock関数を使った例です。
1 | // mockを使ってMockを作る |
ただ上記のコードはshouldReceive
やandReturn
の返り値はmock自身ではないことから
- mockを生成する
- mockを設定する
- mockをバインドする
と記述が3行に渡っています。これはなんかすっきりしない、という人(私)もいると思います。
そこでgetMock()
関数を使ってmock生成と設定を一気にやってしまうことができます。
1 | // ワンライナーで書く |
もしくはmock()
が第2引数に無名関数を取れることを利用してワンライナーっぽく書けます。
1 | // ワンライナーで書く - その2 |
Mockery::mockを使う
Mockery::mock()はmock()
と同じように使えます。
1 | // Mockを作る |
この方法は正直mock()
があるのでわざわざ使わないかなと思います。
2. $this→mock()を使う
前節ではmockを作ってbindするという手順をふんでいましたが、$this→mock()
を使うことでどちらもやってくれます。
以下の例は$this→mock()
を使った例です。
1 |
|
partialMock
関数を使うとpartial mockが作れます。
1 | $this->partialMock(Service::class, |
mock()を使うとき
そんな感じで優秀な$this→mock
なのですが、万能ではありません。
app()→instance()
のかわりにapp()→bind()
を使いたいときにはmock()
を使う必要があります。
例えば、モックするクラスのインスタンスを作る際に引数を渡したいときなどが該当します。
1 | app()->bind( |
私のプロジェクトではapp()->bind()
も使いたかったので、$this->mock
とmock()
が混在しないようにmock()
で統一しようということになりました。
ケースバイケースだったり個人の好みによるところが多いのでチームメンバーと話して決めるのがいいでしょう。
おまけ
上記の例ではいつもonce()
を呼んでいます。
これをしないとモックした関数がテスト中に呼ばれなくてもエラーを吐かないので予期せずテストが通ってしまうことがあります。
shouldReceive
が効いてない!とパニくった実体験が私はあるので、皆さんは気をつけましょう。
まとめ
Laravelには(良くも悪くも)Mockひとつとっても様々な書き方があります。$this→mock
を使うかmock
を使うかはケースバイケースなので、
チームで統一性がとれるルールを選んで使いましょう。
それじゃ今日はこの辺で。
関連記事
こちらの記事もおすすめです。