تم تصميم Mocha ليتم استخدامه في اختبارات الوحدة لأنواع الكائنات الوهمية أو كعب الاختبار للاختبار المزدوج، وليس لأنواع الكائنات المزيفة أو أنواع التجسس الاختباري. على الرغم من أنه سيكون من الممكن توسيع نطاق 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؛ تقوم 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
والتي تتم مشاركتها عبر جميع سلاسل العمليات في عملية روبي ولا تتم مزامنة هذا الوصول إلى الحالة العالمية الفعالة. لذلك، على سبيل المثال، إذا تم تشغيل اختبارين بشكل متزامن واستخدم أحدهما #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.