Mocha предназначен для использования в модульных тестах для типов Mock Object или Test Stub Test Double, а не для типов Fake Object или Test Spy. Хотя можно было бы расширить Mocha, чтобы разрешить реализацию фейков и шпионов, мы решили сосредоточить внимание на макетах и заглушках.
Установите последнюю версию драгоценного камня с помощью следующей команды:
$ gem install mocha
Примечание. Если вы собираетесь использовать Mocha с Test::Unit или Minitest, вам следует настраивать Mocha только после загрузки соответствующей тестовой библиотеки...
require 'rubygems'
gem 'mocha'
require 'test/unit'
require 'mocha/test_unit'
require 'rubygems'
gem 'mocha'
require 'minitest/autorun'
require 'mocha/minitest'
Если вы используете Bundler, включите Mocha в Gemfile
, а затем настройте 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 включает в себя адаптер мокко. Просто скажите RSpec, что вы хотите посмеяться с помощью :mocha
:
# 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
Если вы загружаете Mocha с помощью Bundler в приложении Rails, вам следует настроить Mocha вручную, например, в нижней части файла test_helper.rb
.
Обратите внимание, что начиная с 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, но убедитесь, что соответствующий файл 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.
Возможно, но, вероятно, нет. Частичное макетирование изменяет состояние объектов в ObjectSpace
, которое используется всеми потоками процесса Ruby, и этот доступ к тому, что фактически является глобальным состоянием, не синхронизируется. Так, например, если два теста выполняются одновременно и один из них использует #any_instance
для изменения класса, оба теста немедленно увидят эти изменения.
Заглушки и ожидания — это, по сути, одно и то же. Заглушка — это просто ожидание нуля или более вызовов. Метод 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:<one-time-password> ' 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.