Rubyのテストにスタブを実装する

Rubyのテストは標準のminitestでかなりカバーできますが、スタブとモックについては、 mocha gemを利用した方が良いでしょう。

スタブやモックは、テスト対象のコードが呼び出している一部のメソッドを置き換える機能です。たとえば、マイクロサービス構成の1サービスをテストするためには、API呼び出ししている部分を差し替えないとテストできません。

minitestにもスタブとモックの機能はありますが、オブジェクトを直接指定して定義するため、以下のような強い制約があります。

  • インスタンスメソッドを事実上置き換えられない
  • クラスメソッドを置き換えられるが、事実上1メソッドに限られる

mochaを利用すると、とくにスタブは柔軟に指定でき便利です。

インストールは、bundlerのGemfileにmochaを追加指定してbundle installです。

gem 'mocha'

単純なスタブの例として、インスタンスメソッドを置き換える場合、対象のクラスにany_instanceを指定したうえで、stubs(), returns()により、メソッドと戻り値を定義します。

require 'mocha/minitest'

def setup
  SomeController.any_instance.stubs(:some_method).returns({ status: :ok, message: 'replaced' })
end

後続のテストケース内で該当のメソッドが呼び出されると、returns()に定義した値で処理が続行します。
また、any_instanceを省略すると、クラスメソッドを差し替えます。

mochaはminitestに限らず、Railsのテストとも組み合わせて利用できます。test_helper.rbでrequireしておけば、各テストでは、mochaのメソッドを呼び出せます。

Railsのコントローラーはテストフレームワークが自動でインスタンスを作るため、インスタンスメソッドの差し替えにはany_instanceが必要になります。
また、実サービスが返さないような異常値なども簡単に実装できるため、将来の変更に対しても準備できる点も優れています。

中馬崇尋
Chuma Takahiro