NAKKA-Kの技術ブログ

技術に関する知見や考え方などを投稿します。

Laravel5.7でAPIコントローラーをメソッドとしてテストする方法

LaravelでAPIやコントローラーをテストする方法を調べると、大体出てくるのはサーバーを立ち上げてルーティングに対してリクエストを飛ばしてテストする方法です。 今回はコントローラーのメソッドをそのままテストする方法について記述していきます。

なぜそうしたのか?

簡単に言うとテストが軽くなるからです。 メソッドを一つテストするのにすぎず、サーバーとしての機能を一切使う必要がありません。 もちろんこのテストが通ったからといって、ルーティングなどその他の部分が正しいことを担保することはできません。 しかし一番重要であるコントローラーのメソッドが通ることは担保できます。 個人開発として素早く開発していきたかったので、最小限のコストでクリティカルな部分を担保したかったのでこの方式でテストすることにしました。

やること

基本的なテストクラスの記述は普通のテストとなんら変わりません。 Laravel(composer)の機能で自動ファイル作成してもらって構いません。

ここでやることは以下です。

  • ログインする
  • 任意のリクエストを送る
  • コントローラーのメソッドを実行する
  • 戻ってきたステータスをテストする

テストコード

今回はBookControllerという本を司るコントローラーに、本の作成依頼をするテストをします。

use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Http\Request;

class UserBookControllerTest extends TestCase
{
    use RefreshDatabase;

    protected $user;

    public function setUp()
    {
        parent::setUp();
        $this->user = factory(User::class)->create();
    }

    public function testStoreBook(){
        $this->actingAs($this->user, 'api');

        $request = new Request(['isbn' => '9784063842760']);
        $response = \App::make(BookController::class)->store($request, $this->user);
        $this->assertEquals(201, $response->status());
    }
}

まずユーザーをfactoryで作成します。 factoryの説明はこちらをご覧ください。

このコントローラーへのアクセスはログインが必要なので$this->actingAsを使ってログインします。 引数にユーザーを渡し、第二引数にapiでログインすることを明示します。

次にリクエストを作成します。 Requestのコンストラクタに連想配列を渡してあげるだけです。

次にApp::makeメソッドを使用してテストしたいコントローラーを指定します。 戻り値にコントローラーが帰ってくるのでテストしたいAPIのメソッドを呼び出します。 今回はstore(Request $request, User $user)をテストします。

するとレスポンスが帰ってきますので、statusメソッドを実行すればステータスコードを見ることができます。 もしレスポンスデータもテストしたい場合は$response->getData()を実行ればデータが連想配列で帰ってきます。

モック化

コントローラーをテストするときに、内部で重い処理や外部への問い合わせをしている場合はモック化したいと思います。 Laravelのモック化については記事の範囲外なので、以下の記事を参考にしてください。

nakka-k.hatenablog.com

まとめ

テストが早いと開発の効率もガンガン上がりますよね。 テストは書きたいけど、遅くなるのは嫌だと言う人は、この方法でテストすればある程度テストの実行時間を落とせるかもしれませんね。 良いテスト生活を!