minitestとは
minitestはruby標準のテスティングフレームワーク。
標準だけど、いろいろ経緯があって、バージョンや対応状況がコロコロ変わっていまいち広まってないみたい。
RSpecを使う人が多い中、minitestに関する情報はぐぐってもあんまりない状態(;´Д`)
モジュールメソッドにstubを使う方法
minitestでmockやstubを使う方法はこちら。
http://blog.willnet.in/entry/2012/12/05/004010
ただモジュールメソッドに対して適用する方法はなかなか見つからなかった。
いろいろ試してやっとできたので、紹介します。
以下は指定桁のランダムなhexを生成するという、stub置き換え対象のモジュールメソッド。
require 'securerandom'
module TestModule
module_function
def hex(length)
SecureRandom.hex(length).slice(0, length)
end
end
こういうのをメソッドを利用したクラスをテストするとき、stubに置き換えないとランダムな値のハンドリングがやりづらいという話。
以下がhexメソッドをstubに置き換えたテストケース。
require "minitest/autorun"
describe TestModule, :hex do
describe "when length is passed" do
it "should return hex value" do
test_module_mock = MiniTest::Mock.new
test_module_mock.expect :call, "0123456789abcdef", [16]
TestModule.stub :hex, test_module_mock do
hex = TestModule.hex 16
hex.must_equal "0123456789abcdef"
test_module_mock.verify
end
end
end
end
ポイントは、
test_module_mock.expect :call, "0123456789abcdef", [16]
といった形でMockオブジェクトに対して :call
メソッドを定義するのと、
TestModule.stub :hex, test_module_mock
とstubに置き換えたいメソッドを指定するところ。
なんで:call
なのと思ったら、minitestのstubメソッドの実装にコメントで書いてあった。
# Add a temporary stubbed method replacing +name+ for the duration
# of the +block+. If +val_or_callable+ responds to #call, then it
# returns the result of calling it, otherwise returns the value
# as-is. If stubbed method yields a block, +block_args+ will be
# passed along. Cleans up the stub at the end of the +block+. The
# method +name+ must exist before stubbing.
実装でいうとこのあたり
metaclass.send :define_method, name do |*args, &blk|
ret = if val_or_callable.respond_to? :call then
val_or_callable.call(*args)
else
val_or_callable
end
blk.call(*block_args) if blk
ret
end
miniestに関してはほんとに情報少ないので、ちょっと探してだめなら実装見た方がよっぽど早そうです。