Mocha มีวัตถุประสงค์เพื่อใช้ในการทดสอบหน่วยสำหรับประเภท Mock Object หรือ Test Stub ของ Test Double ไม่ใช่ประเภท Fake Object หรือ Test Spy แม้ว่าจะเป็นไปได้ที่จะขยาย Mocha เพื่อให้สามารถใช้งานของปลอมและสายลับได้ แต่เราเลือกที่จะเน้นไปที่การเยาะเย้ยและต้นขั้ว
ติดตั้ง gem เวอร์ชันล่าสุดด้วยคำสั่งต่อไปนี้...
$ 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
หมายเหตุ: ไม่จำเป็นต้องมีคำสั่ง need เพื่อตั้งค่า 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
ซึ่งแชร์กับเธรดทั้งหมดในกระบวนการ Ruby และการเข้าถึงสถานะส่วนกลางที่มีประสิทธิภาพนี้จะไม่ซิงโครไนซ์ ตัวอย่างเช่น หากการทดสอบสองรายการทำงานพร้อมกัน และรายการหนึ่งใช้ #any_instance
เพื่อแก้ไขคลาส การทดสอบทั้งสองรายการจะเห็นการเปลี่ยนแปลงเหล่านั้นทันที
ต้นขั้วและความคาดหวังโดยพื้นฐานแล้วเป็นสิ่งเดียวกัน ต้นขั้วเป็นเพียงความคาดหวังของการร้องขอเป็นศูนย์หรือมากกว่านั้น เมธอด Expectation#stubs
เป็นการใช้วากยสัมพันธ์เพื่อทำให้จุดประสงค์ของการทดสอบชัดเจนยิ่งขึ้น
เมื่อมีการเรียกใช้เมธอดบนอ็อบเจ็กต์จำลอง อ็อบเจ็กต์จำลองจะค้นหาความคาดหวังจากใหม่ที่สุดไปหาเก่าที่สุดเพื่อค้นหาสิ่งที่ตรงกับการร้องขอ หลังจากการร้องขอ ความคาดหวังที่ตรงกันอาจหยุดการจับคู่การร้องขอเพิ่มเติม
ดูเอกสารประกอบสำหรับ Mocha::Mock
สำหรับรายละเอียดเพิ่มเติม
หากคุณต้องการ Mocha สามารถสร้างคำเตือนหรือแจ้งข้อยกเว้นได้เมื่อ:
ดูเอกสารประกอบสำหรับ Mocha::Configuration
สำหรับรายละเอียดเพิ่มเติม
MOCHA_OPTIONS
เป็นตัวแปรสภาพแวดล้อมที่สามารถตั้งค่าเป็นรายการที่คั่นด้วยเครื่องหมายจุลภาค เพื่อให้เราสามารถระบุได้หลายตัวเลือก เช่น MOCHA_OPTIONS=debug,use_test_unit_gem
ขณะนี้มีเพียงค่าต่อไปนี้เท่านั้นที่ได้รับการยอมรับและมีผลกระทบ:
debug
: เปิดใช้งานโหมดแก้ไขข้อบกพร่องซึ่งจะส่งออก backtraces สำหรับคำเตือนการเลิกใช้งานแต่ละรายการ สิ่งนี้มีประโยชน์สำหรับการค้นหาว่าการโทรที่เลิกใช้แล้วอยู่ที่ใดในชุดทดสอบดูรายชื่อผู้ร่วมให้ข้อมูลนี้
อัปเดตไฟล์ 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