vendor/hardmock/test/functional/stubbing_test.rb in ceedling-0.28.3 vs vendor/hardmock/test/functional/stubbing_test.rb in ceedling-0.29.0
- old
+ new
@@ -1,479 +1,479 @@
-require File.expand_path(File.dirname(__FILE__) + "/../test_helper")
-require 'hardmock'
-require 'assert_error'
-
-class StubbingTest < Test::Unit::TestCase
-
- #
- # TESTS
- #
-
- it "stubs a class method (and un-stubs after reset_stubs)" do
- assert_equal "stones and gravel", Concrete.pour
- assert_equal "glug glug", Jug.pour
-
- Concrete.stubs!(:pour).returns("dust and plaster")
-
- 3.times do
- assert_equal "dust and plaster", Concrete.pour
- end
-
- assert_equal "glug glug", Jug.pour, "Jug's 'pour' method broken"
- assert_equal "stones and gravel", Concrete._hardmock_original_pour, "Original 'pour' method not aliased"
-
- assert_equal "For roads", Concrete.describe, "'describe' method broken"
-
- reset_stubs
-
- assert_equal "stones and gravel", Concrete.pour, "'pour' method not restored"
- assert_equal "For roads", Concrete.describe, "'describe' method broken after verify"
-
- end
-
- it "stubs several class methods" do
- Concrete.stubs!(:pour).returns("sludge")
- Concrete.stubs!(:describe).returns("awful")
- Jug.stubs!(:pour).returns("milk")
-
- assert_equal "sludge", Concrete.pour
- assert_equal "awful", Concrete.describe
- assert_equal "milk", Jug.pour
-
- reset_stubs
-
- assert_equal "stones and gravel", Concrete.pour
- assert_equal "For roads", Concrete.describe
- assert_equal "glug glug", Jug.pour
- end
-
- it "stubs instance methods" do
- slab = Concrete.new
- assert_equal "bonk", slab.hit
-
- slab.stubs!(:hit).returns("slap")
- assert_equal "slap", slab.hit, "'hit' not stubbed"
-
- reset_stubs
-
- assert_equal "bonk", slab.hit, "'hit' not restored"
- end
-
- it "stubs instance methods without breaking class methods or other instances" do
- slab = Concrete.new
- scrape = Concrete.new
- assert_equal "an instance", slab.describe
- assert_equal "an instance", scrape.describe
- assert_equal "For roads", Concrete.describe
-
- slab.stubs!(:describe).returns("new instance describe")
- assert_equal "new instance describe", slab.describe, "'describe' on instance not stubbed"
- assert_equal "an instance", scrape.describe, "'describe' on 'scrape' instance broken"
- assert_equal "For roads", Concrete.describe, "'describe' class method broken"
-
- reset_stubs
-
- assert_equal "an instance", slab.describe, "'describe' instance method not restored"
- assert_equal "an instance", scrape.describe, "'describe' on 'scrape' instance broken after restore"
- assert_equal "For roads", Concrete.describe, "'describe' class method broken after restore"
- end
-
- should "allow stubbing of nonexistant class methods" do
- Concrete.stubs!(:funky).returns('juice')
- assert_equal 'juice', Concrete.funky
- end
-
- should "allow stubbing of nonexistant instance methods" do
- chunk = Concrete.new
- chunk.stubs!(:shark).returns('bite')
- assert_equal 'bite', chunk.shark
- end
-
- should "allow re-stubbing" do
- Concrete.stubs!(:pour).returns("one")
- assert_equal "one", Concrete.pour
-
- Concrete.stubs!(:pour).raises("hell")
- assert_error RuntimeError, /hell/ do
- Concrete.pour
- end
-
- Concrete.stubs!(:pour).returns("two")
- assert_equal "two", Concrete.pour
-
- reset_stubs
-
- assert_equal "stones and gravel", Concrete.pour
- end
-
- it "does nothing with a runtime block when simply stubbing" do
- slab = Concrete.new
- slab.stubs!(:hit) do |nothing|
- raise "BOOOMM!"
- end
- slab.hit
- reset_stubs
- end
-
- it "can raise errors from a stubbed method" do
- Concrete.stubs!(:pour).raises(StandardError.new("no!"))
- assert_error StandardError, /no!/ do
- Concrete.pour
- end
- end
-
- it "provides string syntax for convenient raising of RuntimeErrors" do
- Concrete.stubs!(:pour).raises("never!")
- assert_error RuntimeError, /never!/ do
- Concrete.pour
- end
- end
-
-
- #
- # Per-method mocking on classes or instances
- #
-
- it "mocks specific methods on existing classes, and returns the class method to normal after verification" do
-
- assert_equal "stones and gravel", Concrete.pour, "Concrete.pour is already messed up"
-
- Concrete.expects!(:pour).returns("ALIGATORS")
- assert_equal "ALIGATORS", Concrete.pour
-
- verify_mocks
- assert_equal "stones and gravel", Concrete.pour, "Concrete.pour not restored"
- end
-
- it "flunks if expected class method is not invoked" do
-
- Concrete.expects!(:pour).returns("ALIGATORS")
- assert_error(Hardmock::VerifyError, /Concrete.pour/, /unmet expectations/i) do
- verify_mocks
- end
- clear_expectations
- end
-
- it "supports all normal mock functionality for class methods" do
-
- Concrete.expects!(:pour, "two tons").returns("mice")
- Concrete.expects!(:pour, "three tons").returns("cats")
- Concrete.expects!(:pour, "four tons").raises("Can't do it")
- Concrete.expects!(:pour) do |some, args|
- "==#{some}+#{args}=="
- end
-
- assert_equal "mice", Concrete.pour("two tons")
- assert_equal "cats", Concrete.pour("three tons")
- assert_error(RuntimeError, /Can't do it/) do
- Concrete.pour("four tons")
- end
- assert_equal "==first+second==", Concrete.pour("first","second")
- end
-
-
- it "enforces inter-mock ordering when mocking class methods" do
- create_mocks :truck, :foreman
-
- @truck.expects.backup
- Concrete.expects!(:pour, "something")
- @foreman.expects.shout
-
- @truck.backup
- assert_error Hardmock::ExpectationError, /wrong/i, /expected call/i, /Concrete.pour/ do
- @foreman.shout
- end
- assert_error Hardmock::VerifyError, /unmet expectations/i, /foreman.shout/ do
- verify_mocks
- end
- clear_expectations
- end
-
- should "allow mocking non-existant class methods" do
- Concrete.expects!(:something).returns("else")
- assert_equal "else", Concrete.something
- end
-
- it "mocks specific methods on existing instances, then restore them after verify" do
-
- slab = Concrete.new
- assert_equal "bonk", slab.hit
-
- slab.expects!(:hit).returns("slap")
- assert_equal "slap", slab.hit, "'hit' not stubbed"
-
- verify_mocks
- assert_equal "bonk", slab.hit, "'hit' not restored"
- end
-
- it "flunks if expected instance method is not invoked" do
-
- slab = Concrete.new
- slab.expects!(:hit)
-
- assert_error Hardmock::VerifyError, /unmet expectations/i, /Concrete.hit/ do
- verify_mocks
- end
- clear_expectations
- end
-
- it "supports all normal mock functionality for instance methods" do
-
- slab = Concrete.new
-
- slab.expects!(:hit, "soft").returns("hey")
- slab.expects!(:hit, "hard").returns("OOF")
- slab.expects!(:hit).raises("stoppit")
- slab.expects!(:hit) do |some, args|
- "==#{some}+#{args}=="
- end
-
- assert_equal "hey", slab.hit("soft")
- assert_equal "OOF", slab.hit("hard")
- assert_error(RuntimeError, /stoppit/) do
- slab.hit
- end
- assert_equal "==first+second==", slab.hit("first","second")
-
- end
-
- it "enforces inter-mock ordering when mocking instance methods" do
- create_mocks :truck, :foreman
- slab1 = Concrete.new
- slab2 = Concrete.new
-
- @truck.expects.backup
- slab1.expects!(:hit)
- @foreman.expects.shout
- slab2.expects!(:hit)
- @foreman.expects.whatever
-
- @truck.backup
- slab1.hit
- @foreman.shout
- assert_error Hardmock::ExpectationError, /wrong/i, /expected call/i, /Concrete.hit/ do
- @foreman.whatever
- end
- assert_error Hardmock::VerifyError, /unmet expectations/i, /foreman.whatever/ do
- verify_mocks
- end
- clear_expectations
- end
-
- should "allow mocking non-existant instance methods" do
- slab = Concrete.new
- slab.expects!(:wholly).returns('happy')
- assert_equal 'happy', slab.wholly
- end
-
- should "support concrete expectations that deal with runtime blocks" do
-
- Concrete.expects!(:pour, "a lot") do |how_much, block|
- assert_equal "a lot", how_much, "Wrong how_much arg"
- assert_not_nil block, "nil runtime block"
- assert_equal "the block value", block.call, "Wrong runtime block value"
- end
-
- Concrete.pour("a lot") do
- "the block value"
- end
-
- end
-
- it "can stub methods on mock objects" do
- create_mock :horse
- @horse.stubs!(:speak).returns("silence")
- @horse.stubs!(:hello).returns("nothing")
- @horse.expects(:canter).returns("clip clop")
-
- assert_equal "silence", @horse.speak
- assert_equal "clip clop", @horse.canter
- assert_equal "silence", @horse.speak
- assert_equal "silence", @horse.speak
- assert_equal "nothing", @horse.hello
- assert_equal "nothing", @horse.hello
-
- verify_mocks
- reset_stubs
- end
-
- it "can stub the new method and return values" do
- Concrete.stubs!(:new).returns("this value")
- assert_equal "this value", Concrete.new, "did not properly stub new class method"
- reset_stubs
- end
-
- it "can mock the new method and return values" do
- Concrete.expects!(:new).with("foo").returns("hello")
- Concrete.expects!(:new).with("bar").returns("world")
-
- assert_equal "hello", Concrete.new("foo"), "did not properly mock out new class method"
- assert_equal "world", Concrete.new("bar"), "did not properly mock out new class method"
-
- verify_mocks
- reset_stubs
- end
-
- it "can mock several different class methods at once" do
- sim_code = lambda do |input|
- record = Multitool.find_record(input)
- report = Multitool.generate_report(record)
- Multitool.format_output(report)
- end
-
- @identifier = "the id"
- @record = "the record"
- @report = "the report"
- @output = "the output"
-
- Multitool.expects!(:find_record).with(@identifier).returns(@record)
- Multitool.expects!(:generate_report).with(@record).returns(@report)
- Multitool.expects!(:format_output).with(@report).returns(@output)
-
- result = sim_code.call(@identifier)
- assert_equal @output, result, "Wrong output"
- end
-
- it "can handle a mix of different and repeat class method mock calls" do
- prep = lambda {
- Multitool.expects!(:find_record).with("A").returns("1")
- Multitool.expects!(:generate_report).with("1")
- Multitool.expects!(:find_record).with("B").returns("2")
- Multitool.expects!(:generate_report).with("2")
- }
-
- prep[]
- Multitool.generate_report(Multitool.find_record("A"))
- Multitool.generate_report(Multitool.find_record("B"))
-
- prep[]
- Multitool.generate_report(Multitool.find_record("A"))
- assert_error Hardmock::ExpectationError, /Wrong arguments/, /find_record\("B"\)/, /find_record\("C"\)/ do
- Multitool.generate_report(Multitool.find_record("C"))
- end
- clear_expectations
- end
-
- it "can mock several concrete instance methods at once" do
- inst = OtherMultitool.new
- sim_code = lambda do |input|
- record = inst.find_record(input)
- report = inst.generate_report(record)
- inst.format_output(report)
- end
-
- @identifier = "the id"
- @record = "the record"
- @report = "the report"
- @output = "the output"
-
- inst.expects!(:find_record).with(@identifier).returns(@record)
- inst.expects!(:generate_report).with(@record).returns(@report)
- inst.expects!(:format_output).with(@report).returns(@output)
-
- result = sim_code.call(@identifier)
- assert_equal @output, result, "Wrong output"
- end
-
- it "verifies all concrete expects! from several different expectations" do
- Multitool.expects!(:find_record)
- Multitool.expects!(:generate_report)
- Multitool.expects!(:format_output)
-
- Multitool.find_record
- Multitool.generate_report
-
- assert_error Hardmock::VerifyError, /unmet expectations/i, /format_output/i do
- verify_mocks
- end
- end
-
- it "will not allow expects! to be used on a mock object" do
- create_mock :cow
- assert_error Hardmock::StubbingError, /expects!/, /mock/i, /something/ do
- @cow.expects!(:something)
- end
- end
-
- it "does not allow stubbing on nil objects" do
- [ nil, @this_is_nil ].each do |nil_obj|
- assert_error Hardmock::StubbingError, /cannot/i, /nil/i, /intentionally/ do
- nil_obj.stubs!(:wont_work)
- end
- end
- end
-
- it "does not allow concrete method mocking on nil objects" do
- [ nil, @this_is_nil ].each do |nil_obj|
- assert_error Hardmock::StubbingError, /cannot/i, /nil/i, /intentionally/ do
- nil_obj.expects!(:wont_work)
- end
- end
- end
-
- it "provides an alternate method for stubbing on nil objects" do
- @this_is_nil.intentionally_stubs!(:bogus).returns('output')
- assert_equal 'output', @this_is_nil.bogus
- end
-
- it "provides an alternate method for mocking concreate methods on nil objects" do
- @this_is_nil.intentionally_expects!(:bogus).returns('output')
- assert_error Hardmock::VerifyError, /unmet expectations/i, /NilClass.bogus/ do
- verify_mocks
- end
- end
-
- #
- # HELPERS
- #
-
- class Concrete
- def initialize; end
- def self.pour
- "stones and gravel"
- end
-
- def self.describe
- "For roads"
- end
-
- def hit
- "bonk"
- end
-
- def describe
- "an instance"
- end
- end
-
- class Jug
- def self.pour
- "glug glug"
- end
- end
-
- class Multitool
- def self.find_record(*a)
- raise "The real Multitool.find_record was called with #{a.inspect}"
- end
- def self.generate_report(*a)
- raise "The real Multitool.generate_report was called with #{a.inspect}"
- end
- def self.format_output(*a)
- raise "The real Multitool.format_output was called with #{a.inspect}"
- end
- end
-
- class OtherMultitool
- def find_record(*a)
- raise "The real OtherMultitool#find_record was called with #{a.inspect}"
- end
- def generate_report(*a)
- raise "The real OtherMultitool#generate_report was called with #{a.inspect}"
- end
- def format_output(*a)
- raise "The real OtherMultitool#format_output was called with #{a.inspect}"
- end
- end
-
-end
-
+require File.expand_path(File.dirname(__FILE__) + "/../test_helper")
+require 'hardmock'
+require 'assert_error'
+
+class StubbingTest < Test::Unit::TestCase
+
+ #
+ # TESTS
+ #
+
+ it "stubs a class method (and un-stubs after reset_stubs)" do
+ assert_equal "stones and gravel", Concrete.pour
+ assert_equal "glug glug", Jug.pour
+
+ Concrete.stubs!(:pour).returns("dust and plaster")
+
+ 3.times do
+ assert_equal "dust and plaster", Concrete.pour
+ end
+
+ assert_equal "glug glug", Jug.pour, "Jug's 'pour' method broken"
+ assert_equal "stones and gravel", Concrete._hardmock_original_pour, "Original 'pour' method not aliased"
+
+ assert_equal "For roads", Concrete.describe, "'describe' method broken"
+
+ reset_stubs
+
+ assert_equal "stones and gravel", Concrete.pour, "'pour' method not restored"
+ assert_equal "For roads", Concrete.describe, "'describe' method broken after verify"
+
+ end
+
+ it "stubs several class methods" do
+ Concrete.stubs!(:pour).returns("sludge")
+ Concrete.stubs!(:describe).returns("awful")
+ Jug.stubs!(:pour).returns("milk")
+
+ assert_equal "sludge", Concrete.pour
+ assert_equal "awful", Concrete.describe
+ assert_equal "milk", Jug.pour
+
+ reset_stubs
+
+ assert_equal "stones and gravel", Concrete.pour
+ assert_equal "For roads", Concrete.describe
+ assert_equal "glug glug", Jug.pour
+ end
+
+ it "stubs instance methods" do
+ slab = Concrete.new
+ assert_equal "bonk", slab.hit
+
+ slab.stubs!(:hit).returns("slap")
+ assert_equal "slap", slab.hit, "'hit' not stubbed"
+
+ reset_stubs
+
+ assert_equal "bonk", slab.hit, "'hit' not restored"
+ end
+
+ it "stubs instance methods without breaking class methods or other instances" do
+ slab = Concrete.new
+ scrape = Concrete.new
+ assert_equal "an instance", slab.describe
+ assert_equal "an instance", scrape.describe
+ assert_equal "For roads", Concrete.describe
+
+ slab.stubs!(:describe).returns("new instance describe")
+ assert_equal "new instance describe", slab.describe, "'describe' on instance not stubbed"
+ assert_equal "an instance", scrape.describe, "'describe' on 'scrape' instance broken"
+ assert_equal "For roads", Concrete.describe, "'describe' class method broken"
+
+ reset_stubs
+
+ assert_equal "an instance", slab.describe, "'describe' instance method not restored"
+ assert_equal "an instance", scrape.describe, "'describe' on 'scrape' instance broken after restore"
+ assert_equal "For roads", Concrete.describe, "'describe' class method broken after restore"
+ end
+
+ should "allow stubbing of nonexistant class methods" do
+ Concrete.stubs!(:funky).returns('juice')
+ assert_equal 'juice', Concrete.funky
+ end
+
+ should "allow stubbing of nonexistant instance methods" do
+ chunk = Concrete.new
+ chunk.stubs!(:shark).returns('bite')
+ assert_equal 'bite', chunk.shark
+ end
+
+ should "allow re-stubbing" do
+ Concrete.stubs!(:pour).returns("one")
+ assert_equal "one", Concrete.pour
+
+ Concrete.stubs!(:pour).raises("hell")
+ assert_error RuntimeError, /hell/ do
+ Concrete.pour
+ end
+
+ Concrete.stubs!(:pour).returns("two")
+ assert_equal "two", Concrete.pour
+
+ reset_stubs
+
+ assert_equal "stones and gravel", Concrete.pour
+ end
+
+ it "does nothing with a runtime block when simply stubbing" do
+ slab = Concrete.new
+ slab.stubs!(:hit) do |nothing|
+ raise "BOOOMM!"
+ end
+ slab.hit
+ reset_stubs
+ end
+
+ it "can raise errors from a stubbed method" do
+ Concrete.stubs!(:pour).raises(StandardError.new("no!"))
+ assert_error StandardError, /no!/ do
+ Concrete.pour
+ end
+ end
+
+ it "provides string syntax for convenient raising of RuntimeErrors" do
+ Concrete.stubs!(:pour).raises("never!")
+ assert_error RuntimeError, /never!/ do
+ Concrete.pour
+ end
+ end
+
+
+ #
+ # Per-method mocking on classes or instances
+ #
+
+ it "mocks specific methods on existing classes, and returns the class method to normal after verification" do
+
+ assert_equal "stones and gravel", Concrete.pour, "Concrete.pour is already messed up"
+
+ Concrete.expects!(:pour).returns("ALIGATORS")
+ assert_equal "ALIGATORS", Concrete.pour
+
+ verify_mocks
+ assert_equal "stones and gravel", Concrete.pour, "Concrete.pour not restored"
+ end
+
+ it "flunks if expected class method is not invoked" do
+
+ Concrete.expects!(:pour).returns("ALIGATORS")
+ assert_error(Hardmock::VerifyError, /Concrete.pour/, /unmet expectations/i) do
+ verify_mocks
+ end
+ clear_expectations
+ end
+
+ it "supports all normal mock functionality for class methods" do
+
+ Concrete.expects!(:pour, "two tons").returns("mice")
+ Concrete.expects!(:pour, "three tons").returns("cats")
+ Concrete.expects!(:pour, "four tons").raises("Can't do it")
+ Concrete.expects!(:pour) do |some, args|
+ "==#{some}+#{args}=="
+ end
+
+ assert_equal "mice", Concrete.pour("two tons")
+ assert_equal "cats", Concrete.pour("three tons")
+ assert_error(RuntimeError, /Can't do it/) do
+ Concrete.pour("four tons")
+ end
+ assert_equal "==first+second==", Concrete.pour("first","second")
+ end
+
+
+ it "enforces inter-mock ordering when mocking class methods" do
+ create_mocks :truck, :foreman
+
+ @truck.expects.backup
+ Concrete.expects!(:pour, "something")
+ @foreman.expects.shout
+
+ @truck.backup
+ assert_error Hardmock::ExpectationError, /wrong/i, /expected call/i, /Concrete.pour/ do
+ @foreman.shout
+ end
+ assert_error Hardmock::VerifyError, /unmet expectations/i, /foreman.shout/ do
+ verify_mocks
+ end
+ clear_expectations
+ end
+
+ should "allow mocking non-existant class methods" do
+ Concrete.expects!(:something).returns("else")
+ assert_equal "else", Concrete.something
+ end
+
+ it "mocks specific methods on existing instances, then restore them after verify" do
+
+ slab = Concrete.new
+ assert_equal "bonk", slab.hit
+
+ slab.expects!(:hit).returns("slap")
+ assert_equal "slap", slab.hit, "'hit' not stubbed"
+
+ verify_mocks
+ assert_equal "bonk", slab.hit, "'hit' not restored"
+ end
+
+ it "flunks if expected instance method is not invoked" do
+
+ slab = Concrete.new
+ slab.expects!(:hit)
+
+ assert_error Hardmock::VerifyError, /unmet expectations/i, /Concrete.hit/ do
+ verify_mocks
+ end
+ clear_expectations
+ end
+
+ it "supports all normal mock functionality for instance methods" do
+
+ slab = Concrete.new
+
+ slab.expects!(:hit, "soft").returns("hey")
+ slab.expects!(:hit, "hard").returns("OOF")
+ slab.expects!(:hit).raises("stoppit")
+ slab.expects!(:hit) do |some, args|
+ "==#{some}+#{args}=="
+ end
+
+ assert_equal "hey", slab.hit("soft")
+ assert_equal "OOF", slab.hit("hard")
+ assert_error(RuntimeError, /stoppit/) do
+ slab.hit
+ end
+ assert_equal "==first+second==", slab.hit("first","second")
+
+ end
+
+ it "enforces inter-mock ordering when mocking instance methods" do
+ create_mocks :truck, :foreman
+ slab1 = Concrete.new
+ slab2 = Concrete.new
+
+ @truck.expects.backup
+ slab1.expects!(:hit)
+ @foreman.expects.shout
+ slab2.expects!(:hit)
+ @foreman.expects.whatever
+
+ @truck.backup
+ slab1.hit
+ @foreman.shout
+ assert_error Hardmock::ExpectationError, /wrong/i, /expected call/i, /Concrete.hit/ do
+ @foreman.whatever
+ end
+ assert_error Hardmock::VerifyError, /unmet expectations/i, /foreman.whatever/ do
+ verify_mocks
+ end
+ clear_expectations
+ end
+
+ should "allow mocking non-existant instance methods" do
+ slab = Concrete.new
+ slab.expects!(:wholly).returns('happy')
+ assert_equal 'happy', slab.wholly
+ end
+
+ should "support concrete expectations that deal with runtime blocks" do
+
+ Concrete.expects!(:pour, "a lot") do |how_much, block|
+ assert_equal "a lot", how_much, "Wrong how_much arg"
+ assert_not_nil block, "nil runtime block"
+ assert_equal "the block value", block.call, "Wrong runtime block value"
+ end
+
+ Concrete.pour("a lot") do
+ "the block value"
+ end
+
+ end
+
+ it "can stub methods on mock objects" do
+ create_mock :horse
+ @horse.stubs!(:speak).returns("silence")
+ @horse.stubs!(:hello).returns("nothing")
+ @horse.expects(:canter).returns("clip clop")
+
+ assert_equal "silence", @horse.speak
+ assert_equal "clip clop", @horse.canter
+ assert_equal "silence", @horse.speak
+ assert_equal "silence", @horse.speak
+ assert_equal "nothing", @horse.hello
+ assert_equal "nothing", @horse.hello
+
+ verify_mocks
+ reset_stubs
+ end
+
+ it "can stub the new method and return values" do
+ Concrete.stubs!(:new).returns("this value")
+ assert_equal "this value", Concrete.new, "did not properly stub new class method"
+ reset_stubs
+ end
+
+ it "can mock the new method and return values" do
+ Concrete.expects!(:new).with("foo").returns("hello")
+ Concrete.expects!(:new).with("bar").returns("world")
+
+ assert_equal "hello", Concrete.new("foo"), "did not properly mock out new class method"
+ assert_equal "world", Concrete.new("bar"), "did not properly mock out new class method"
+
+ verify_mocks
+ reset_stubs
+ end
+
+ it "can mock several different class methods at once" do
+ sim_code = lambda do |input|
+ record = Multitool.find_record(input)
+ report = Multitool.generate_report(record)
+ Multitool.format_output(report)
+ end
+
+ @identifier = "the id"
+ @record = "the record"
+ @report = "the report"
+ @output = "the output"
+
+ Multitool.expects!(:find_record).with(@identifier).returns(@record)
+ Multitool.expects!(:generate_report).with(@record).returns(@report)
+ Multitool.expects!(:format_output).with(@report).returns(@output)
+
+ result = sim_code.call(@identifier)
+ assert_equal @output, result, "Wrong output"
+ end
+
+ it "can handle a mix of different and repeat class method mock calls" do
+ prep = lambda {
+ Multitool.expects!(:find_record).with("A").returns("1")
+ Multitool.expects!(:generate_report).with("1")
+ Multitool.expects!(:find_record).with("B").returns("2")
+ Multitool.expects!(:generate_report).with("2")
+ }
+
+ prep[]
+ Multitool.generate_report(Multitool.find_record("A"))
+ Multitool.generate_report(Multitool.find_record("B"))
+
+ prep[]
+ Multitool.generate_report(Multitool.find_record("A"))
+ assert_error Hardmock::ExpectationError, /Wrong arguments/, /find_record\("B"\)/, /find_record\("C"\)/ do
+ Multitool.generate_report(Multitool.find_record("C"))
+ end
+ clear_expectations
+ end
+
+ it "can mock several concrete instance methods at once" do
+ inst = OtherMultitool.new
+ sim_code = lambda do |input|
+ record = inst.find_record(input)
+ report = inst.generate_report(record)
+ inst.format_output(report)
+ end
+
+ @identifier = "the id"
+ @record = "the record"
+ @report = "the report"
+ @output = "the output"
+
+ inst.expects!(:find_record).with(@identifier).returns(@record)
+ inst.expects!(:generate_report).with(@record).returns(@report)
+ inst.expects!(:format_output).with(@report).returns(@output)
+
+ result = sim_code.call(@identifier)
+ assert_equal @output, result, "Wrong output"
+ end
+
+ it "verifies all concrete expects! from several different expectations" do
+ Multitool.expects!(:find_record)
+ Multitool.expects!(:generate_report)
+ Multitool.expects!(:format_output)
+
+ Multitool.find_record
+ Multitool.generate_report
+
+ assert_error Hardmock::VerifyError, /unmet expectations/i, /format_output/i do
+ verify_mocks
+ end
+ end
+
+ it "will not allow expects! to be used on a mock object" do
+ create_mock :cow
+ assert_error Hardmock::StubbingError, /expects!/, /mock/i, /something/ do
+ @cow.expects!(:something)
+ end
+ end
+
+ it "does not allow stubbing on nil objects" do
+ [ nil, @this_is_nil ].each do |nil_obj|
+ assert_error Hardmock::StubbingError, /cannot/i, /nil/i, /intentionally/ do
+ nil_obj.stubs!(:wont_work)
+ end
+ end
+ end
+
+ it "does not allow concrete method mocking on nil objects" do
+ [ nil, @this_is_nil ].each do |nil_obj|
+ assert_error Hardmock::StubbingError, /cannot/i, /nil/i, /intentionally/ do
+ nil_obj.expects!(:wont_work)
+ end
+ end
+ end
+
+ it "provides an alternate method for stubbing on nil objects" do
+ @this_is_nil.intentionally_stubs!(:bogus).returns('output')
+ assert_equal 'output', @this_is_nil.bogus
+ end
+
+ it "provides an alternate method for mocking concreate methods on nil objects" do
+ @this_is_nil.intentionally_expects!(:bogus).returns('output')
+ assert_error Hardmock::VerifyError, /unmet expectations/i, /NilClass.bogus/ do
+ verify_mocks
+ end
+ end
+
+ #
+ # HELPERS
+ #
+
+ class Concrete
+ def initialize; end
+ def self.pour
+ "stones and gravel"
+ end
+
+ def self.describe
+ "For roads"
+ end
+
+ def hit
+ "bonk"
+ end
+
+ def describe
+ "an instance"
+ end
+ end
+
+ class Jug
+ def self.pour
+ "glug glug"
+ end
+ end
+
+ class Multitool
+ def self.find_record(*a)
+ raise "The real Multitool.find_record was called with #{a.inspect}"
+ end
+ def self.generate_report(*a)
+ raise "The real Multitool.generate_report was called with #{a.inspect}"
+ end
+ def self.format_output(*a)
+ raise "The real Multitool.format_output was called with #{a.inspect}"
+ end
+ end
+
+ class OtherMultitool
+ def find_record(*a)
+ raise "The real OtherMultitool#find_record was called with #{a.inspect}"
+ end
+ def generate_report(*a)
+ raise "The real OtherMultitool#generate_report was called with #{a.inspect}"
+ end
+ def format_output(*a)
+ raise "The real OtherMultitool#format_output was called with #{a.inspect}"
+ end
+ end
+
+end
+