Mocha は、Fake Object や Test Spy タイプではなく、Test Double の Mock Object または Test Stub タイプの単体テストで使用することを目的としています。 Mocha を拡張してフェイクやスパイの実装を許可することも可能ですが、モックとスタブに重点を置くことにしました。
次のコマンドを使用して、Gem の最新バージョンをインストールします...
$ gem install mocha
注: Test::Unit または Minitest で Mocha を使用する場合は、関連するテスト ライブラリをロードした後にのみMocha をセットアップする必要があります。
require 'rubygems'
gem 'mocha'
require 'test/unit'
require 'mocha/test_unit'
require 'rubygems'
gem 'mocha'
require 'minitest/autorun'
require 'mocha/minitest'
Bundler を使用している場合は、 Gemfile
に Mocha を含めて、テスト ライブラリがロードされたことがわかったら、後で Mocha をセットアップします。
# Gemfile
gem 'mocha'
# Elsewhere after Bundler has loaded gems e.g. after `require 'bundler/setup'`
require 'test/unit'
require 'mocha/test_unit'
# Gemfile
gem 'mocha'
# Elsewhere after Bundler has loaded gems e.g. after `require 'bundler/setup'`
require 'minitest/autorun'
require 'mocha/minitest'
RSpec には mocha アダプターが含まれています。 : :mocha
でモックしたいことを RSpec に伝えるだけです。
# Gemfile in Rails app
gem 'mocha'
# Within `spec/spec_helper.rb`
RSpec . configure do | config |
config . mock_with :mocha
end
注: Mocha をセットアップするために require ステートメントを使用する必要はありません。 RSpec 自体がこれを行います。
# In e.g. features/support/mocha.rb
require 'mocha/api'
World ( Mocha :: API )
Around do | scenario , block |
begin
mocha_setup
block . call
mocha_verify
ensure
mocha_teardown
end
end
Rails アプリケーション内で Bundler を使用して Mocha をロードしている場合は、たとえばtest_helper.rb
の下部で Mocha を手動でセットアップする必要があります。
Rails v4 (少なくとも) 以降、 ActiveSupport::TestCase
Minitest::Test
またはそれ以前の同等のものから継承していることに注意してください。したがって、明示的にTest::Unit を使用していない限り、Minitest を使用することになるでしょう。
# Gemfile in Rails app
gem 'mocha'
# At bottom of test_helper.rb (or at least after `require 'rails/test_help'`)
require 'mocha/minitest'
Bundler セクションの関連するテスト フレームワークの指示に従いますが、テスト フレームワークがロードされた後、たとえばtest_helper.rb
の下部に関連する Mocha ファイル ( mocha/minitest
、 mocha/test_unit
、またはmocha/api
) が必要であることを確認してください。 test_helper.rb
またはspec_helper.rb
、または少なくともrails/test_help
が必要になった後。
extend
に使用されるモジュール内で元のメソッドが定義されているエイリアス化されたクラス メソッドのスタブは、Ruby v1.8 では機能しません。この動作の例については、 test/acceptance/stub_method_defined_on_module_and_aliased_test.rb
を参照してください。 require 'test/unit'
require 'mocha/test_unit'
class MiscExampleTest < Test :: Unit :: TestCase
def test_mocking_a_class_method
product = Product . new
Product . expects ( :find ) . with ( 1 ) . returns ( product )
assert_equal product , Product . find ( 1 )
end
def test_mocking_an_instance_method_on_a_real_object
product = Product . new
product . expects ( :save ) . returns ( true )
assert product . save
end
def test_stubbing_instance_methods_on_real_objects
prices = [ stub ( pence : 1000 ) , stub ( pence : 2000 ) ]
product = Product . new
product . stubs ( :prices ) . returns ( prices )
assert_equal [ 1000 , 2000 ] , product . prices . collect { | p | p . pence }
end
def test_stubbing_an_instance_method_on_all_instances_of_a_class
Product . any_instance . stubs ( :name ) . returns ( 'stubbed_name' )
product = Product . new
assert_equal 'stubbed_name' , product . name
end
def test_traditional_mocking
object = mock ( 'object' )
object . expects ( :expected_method ) . with ( :p1 , :p2 ) . returns ( :result )
assert_equal :result , object . expected_method ( :p1 , :p2 )
end
def test_shortcuts
object = stub ( method1 : :result1 , method2 : :result2 )
assert_equal :result1 , object . method1
assert_equal :result2 , object . method2
end
end
class Enterprise
def initialize ( dilithium )
@dilithium = dilithium
end
def go ( warp_factor )
warp_factor . times { @dilithium . nuke ( :anti_matter ) }
end
end
require 'test/unit'
require 'mocha/test_unit'
class EnterpriseTest < Test :: Unit :: TestCase
def test_should_boldly_go
dilithium = mock ( )
dilithium . expects ( :nuke ) . with ( :anti_matter ) . at_least_once # auto-verified at end of test
enterprise = Enterprise . new ( dilithium )
enterprise . go ( 2 )
end
end
class Order
attr_accessor :shipped_on
def total_cost
line_items . inject ( 0 ) { | total , line_item | total + line_item . price } + shipping_cost
end
def total_weight
line_items . inject ( 0 ) { | total , line_item | total + line_item . weight }
end
def shipping_cost
total_weight * 5 + 10
end
class << self
def find_all
# Database.connection.execute('select * from orders...
end
def number_shipped_since ( date )
find_all . select { | order | order . shipped_on > date } . length
end
def unshipped_value
find_all . inject ( 0 ) { | total , order | order . shipped_on ? total : total + order . total_cost }
end
end
end
require 'test/unit'
require 'mocha/test_unit'
class OrderTest < Test :: Unit :: TestCase
# illustrates stubbing instance method
def test_should_calculate_shipping_cost_based_on_total_weight
order = Order . new
order . stubs ( :total_weight ) . returns ( 10 )
assert_equal 60 , order . shipping_cost
end
# illustrates stubbing class method
def test_should_count_number_of_orders_shipped_after_specified_date
now = Time . now ; week_in_secs = 7 * 24 * 60 * 60
order_1 = Order . new ; order_1 . shipped_on = now - 1 * week_in_secs
order_2 = Order . new ; order_2 . shipped_on = now - 3 * week_in_secs
Order . stubs ( :find_all ) . returns ( [ order_1 , order_2 ] )
assert_equal 1 , Order . number_shipped_since ( now - 2 * week_in_secs )
end
# illustrates stubbing instance method for all instances of a class
def test_should_calculate_value_of_unshipped_orders
Order . stubs ( :find_all ) . returns ( [ Order . new , Order . new , Order . new ] )
Order . any_instance . stubs ( :shipped_on ) . returns ( nil )
Order . any_instance . stubs ( :total_cost ) . returns ( 10 )
assert_equal 30 , Order . unshipped_value
end
end
Mocha は現在、スレッドセーフであることを目指していません。
短い答えはノーです。マルチスレッド コードでは、テストを実行しているスレッド以外のスレッドで Mocha 例外が発生する可能性があるため、Mocha 例外が Mocha 例外処理コードによって正しくインターセプトされない可能性があります。
おそらく、しかしおそらくそうではありません。部分モックでは、Ruby プロセスのすべてのスレッドで共有されるObjectSpace
内のオブジェクトの状態が変更され、事実上グローバルな状態へのアクセスは同期されません。したがって、たとえば、2 つのテストが同時に実行されており、1 つが#any_instance
使用してクラスを変更した場合、両方のテストでそれらの変更がすぐに確認されます。
スタブと期待値は基本的に同じものです。スタブは、0 回以上の呼び出しを期待するものにすぎません。 Expectation#stubs
メソッドは、テストの意図をより明確にするための糖衣構文です。
モック オブジェクトでメソッドが呼び出されると、モック オブジェクトはその期待値を最新のものから最も古いものまで検索して、呼び出しに一致するものを見つけます。呼び出し後、一致する期待値は、それ以降の呼び出しの一致を停止する可能性があります。
詳細については、 Mocha::Mock
のドキュメントを参照してください。
必要に応じて、Mocha は次の場合に警告を生成したり、例外を発生させたりできます。
詳細については、 Mocha::Configuration
のドキュメントを参照してください。
MOCHA_OPTIONS
は環境変数であり、その値をカンマ区切りのリストに設定できるため、複数のオプションを指定できます (例: MOCHA_OPTIONS=debug,use_test_unit_gem
。現在認識され、影響を与えるのは次の値のみです。
debug
: 非推奨の警告ごとにバックトレースを出力するデバッグ モードを有効にします。これは、テスト スイート内の非推奨の呼び出しがどこにあるかを見つけるのに役立ちます。この寄稿者のリストを参照してください。
変更の概要を使用して RELEASE.md ファイルを更新します。
lib/mocha/version.rb
のバージョンをバンプします。
GitHub にコミットしてプッシュする
CircleCI ビルドが成功していることを確認する - https://app.circleci.com/pipelines/github/freerange/mocha
ドキュメントを生成します。
$ MOCHA_GENERATE_DOCS=true bundle install
$ MOCHA_GENERATE_DOCS=true rake generate_docs
$ curl -u < email-address > -H ' OTP: ' https://rubygems.org/api/v1/api_key.yaml > ~ /.gem/credentials ; chmod 0600 ~ /.gem/credentials
$ rake release
[runs tests]
mocha 1.2.0 built to pkg/mocha-1.2.0.gem.
Tagged v1.2.0.
Pushed git commits and tags.
Pushed mocha 1.2.0 to rubygems.org.
モカは当初、Reevoo のプロジェクトから採取されました。その構文は jMock の構文に大きく基づいています。
© 著作権ジェームズ・ミード 2006
このライブラリは、Ruby 自体と同じ条件または MIT ライセンスに基づいて使用、コピー、再配布することができます。