rr 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. data/CHANGES +1 -0
  2. data/README +45 -0
  3. data/Rakefile +60 -0
  4. data/examples/environment_fixture_setup.rb +7 -0
  5. data/examples/example_helper.rb +8 -0
  6. data/examples/example_suite.rb +45 -0
  7. data/examples/high_level_example.rb +132 -0
  8. data/examples/rr/do_not_allow_creator_example.rb +90 -0
  9. data/examples/rr/double_bind_example.rb +32 -0
  10. data/examples/rr/double_dispatching_example.rb +167 -0
  11. data/examples/rr/double_example.rb +67 -0
  12. data/examples/rr/double_register_scenario_example.rb +25 -0
  13. data/examples/rr/double_reset_example.rb +60 -0
  14. data/examples/rr/double_verify_example.rb +24 -0
  15. data/examples/rr/expectations/any_argument_expectation_example.rb +43 -0
  16. data/examples/rr/expectations/anything_argument_equality_expectation_example.rb +39 -0
  17. data/examples/rr/expectations/argument_equality_expectation_example.rb +53 -0
  18. data/examples/rr/expectations/boolean_argument_equality_expectation_example.rb +49 -0
  19. data/examples/rr/expectations/duck_type_argument_equality_expectation_example.rb +68 -0
  20. data/examples/rr/expectations/is_a_argument_equality_expectation_example.rb +51 -0
  21. data/examples/rr/expectations/numeric_argument_equality_expectation_example.rb +47 -0
  22. data/examples/rr/expectations/range_argument_equality_expectation_example.rb +60 -0
  23. data/examples/rr/expectations/regexp_argument_equality_expectation_example.rb +68 -0
  24. data/examples/rr/expectations/times_called_expectation_example.rb +176 -0
  25. data/examples/rr/extensions/double_methods_example.rb +130 -0
  26. data/examples/rr/mock_creator_example.rb +65 -0
  27. data/examples/rr/probe_creator_example.rb +83 -0
  28. data/examples/rr/rspec/rspec_adapter_example.rb +64 -0
  29. data/examples/rr/rspec/rspec_usage_example.rb +38 -0
  30. data/examples/rr/scenario_example.rb +399 -0
  31. data/examples/rr/space_create_example.rb +185 -0
  32. data/examples/rr/space_example.rb +30 -0
  33. data/examples/rr/space_helper.rb +7 -0
  34. data/examples/rr/space_register_example.rb +33 -0
  35. data/examples/rr/space_reset_example.rb +73 -0
  36. data/examples/rr/space_verify_example.rb +146 -0
  37. data/examples/rr/stub_creator_example.rb +74 -0
  38. data/examples/rr/test_unit/test_helper.rb +9 -0
  39. data/examples/rr/test_unit/test_unit_integration_test.rb +39 -0
  40. data/examples/rspec_example_suite.rb +25 -0
  41. data/examples/test_unit_example_suite.rb +21 -0
  42. data/lib/rr.rb +27 -0
  43. data/lib/rr/adapters/rspec.rb +19 -0
  44. data/lib/rr/adapters/test_unit.rb +27 -0
  45. data/lib/rr/do_not_allow_creator.rb +39 -0
  46. data/lib/rr/double.rb +91 -0
  47. data/lib/rr/expectations/any_argument_expectation.rb +17 -0
  48. data/lib/rr/expectations/argument_equality_expectation.rb +35 -0
  49. data/lib/rr/expectations/times_called_expectation.rb +39 -0
  50. data/lib/rr/expectations/wildcard_matchers/anything.rb +15 -0
  51. data/lib/rr/expectations/wildcard_matchers/boolean.rb +20 -0
  52. data/lib/rr/expectations/wildcard_matchers/duck_type.rb +26 -0
  53. data/lib/rr/expectations/wildcard_matchers/is_a.rb +22 -0
  54. data/lib/rr/expectations/wildcard_matchers/numeric.rb +11 -0
  55. data/lib/rr/expectations/wildcard_matchers/range.rb +7 -0
  56. data/lib/rr/expectations/wildcard_matchers/regexp.rb +7 -0
  57. data/lib/rr/extensions/double_methods.rb +81 -0
  58. data/lib/rr/mock_creator.rb +32 -0
  59. data/lib/rr/probe_creator.rb +31 -0
  60. data/lib/rr/scenario.rb +184 -0
  61. data/lib/rr/scenario_not_found_error.rb +4 -0
  62. data/lib/rr/scenario_order_error.rb +4 -0
  63. data/lib/rr/space.rb +111 -0
  64. data/lib/rr/stub_creator.rb +36 -0
  65. metadata +113 -0
data/CHANGES ADDED
@@ -0,0 +1 @@
1
+ * 0.1.0
data/README ADDED
@@ -0,0 +1,45 @@
1
+ = RR
2
+
3
+ RR (Double Ruby) is a double framework that features a rich
4
+ selection of double techniques and a terse syntax.
5
+ http://xunitpatterns.com/Test%20Double.html
6
+
7
+ Currently RR implements mocks, stubs, and probes. It is a goal of
8
+ RR to support a wide range of double techniques and patterns.
9
+
10
+ == Mocking
11
+ http://xunitpatterns.com/Mock%20Object.html
12
+ view = controller.template
13
+ mock(view).render(:partial => "user_info") {"Information"}
14
+
15
+ == Stubbing
16
+ http://xunitpatterns.com/Test%20Stub.html
17
+ jane = User.new
18
+ stub(User).find('42') {jane}
19
+ mock(jane).valid? {true}
20
+
21
+ == Probing
22
+ Add verifications that a method was called while actually calling it.
23
+ The following example verifies render partial will be called and
24
+ renders the partial.
25
+
26
+ view = controller.template
27
+ probe(view).render(:partial => "user_info")
28
+
29
+ == Block Syntax
30
+ script = MyScript.new
31
+ mock(script) do |m|
32
+ m.system("cd #{RAILS_ENV}") {true}
33
+ m.system("rake foo:bar") {true}
34
+ m.system("rake baz") {true}
35
+ end
36
+
37
+ == Terse Syntax
38
+ One of the goals of RR is to make doubles more scannable.
39
+ This is accomplished by removing words from a double declaration.
40
+ Here is RR compared to other mock frameworks:
41
+
42
+ flexmock(User).should_receive(:find).with('42').and_return(jane) # Flexmock
43
+ User.should_receive(:find).with('42').and_return(jane) # Rspec
44
+ User.expects(:find).with('42').returns {jane} # Mocha
45
+ mock(User).find('42') {jane} # RR
@@ -0,0 +1,60 @@
1
+ require "rake"
2
+ require 'rake/gempackagetask'
3
+ require 'rake/contrib/rubyforgepublisher'
4
+ require 'rake/clean'
5
+ require 'rake/testtask'
6
+ require 'rake/rdoctask'
7
+
8
+ desc "Runs the Rspec suite"
9
+ task(:default) do
10
+ run_suite
11
+ end
12
+
13
+ desc "Runs the Rspec suite"
14
+ task(:spec) do
15
+ run_suite
16
+ end
17
+
18
+ def run_suite
19
+ dir = File.dirname(__FILE__)
20
+ system("ruby #{dir}/examples/example_suite.rb") || raise("Example Suite failed")
21
+ end
22
+
23
+ PKG_NAME = "rr"
24
+ PKG_VERSION = "0.1.0"
25
+ PKG_FILES = FileList[
26
+ '[A-Z]*',
27
+ '*.rb',
28
+ 'lib/**/*.rb',
29
+ 'examples/**/*.rb'
30
+ ]
31
+
32
+ spec = Gem::Specification.new do |s|
33
+ s.name = PKG_NAME
34
+ s.version = PKG_VERSION
35
+ s.summary = "RR (Double Ruby) is a double framework that features a rich " <<
36
+ "selection of double techniques and a terse syntax. " <<
37
+ "http://xunitpatterns.com/Test%20Double.html"
38
+ s.test_files = "examples/example_suite.rb"
39
+ s.description = s.summary
40
+
41
+ s.files = PKG_FILES.to_a
42
+ s.require_path = 'lib'
43
+
44
+ s.has_rdoc = true
45
+ s.extra_rdoc_files = [ "README", "CHANGES" ]
46
+ s.rdoc_options = ["--main", "README", "--inline-source", "--line-numbers"]
47
+
48
+ s.test_files = Dir.glob('spec/*_spec.rb')
49
+ s.require_path = 'lib'
50
+ s.autorequire = 'rr'
51
+ s.author = "Brian Takita"
52
+ s.email = "brian@pivotallabs.com"
53
+ s.homepage = "http://pivotallabs.com"
54
+ s.rubyforge_project = "pivotalrb"
55
+ end
56
+
57
+ Rake::GemPackageTask.new(spec) do |pkg|
58
+ pkg.need_zip = true
59
+ pkg.need_tar = true
60
+ end
@@ -0,0 +1,7 @@
1
+ require "rubygems"
2
+ require "spec"
3
+ dir = File.dirname(__FILE__)
4
+ $LOAD_PATH << "#{dir}/../lib"
5
+ require "rr"
6
+ require "ruby-debug"
7
+ require "pp"
@@ -0,0 +1,8 @@
1
+ dir = File.dirname(__FILE__)
2
+ require "#{dir}/environment_fixture_setup"
3
+ require "examples/rr/space_helper"
4
+
5
+ require "rr/adapters/rspec"
6
+ Spec::Runner.configure do |config|
7
+ config.mock_with RR::Adapters::Rspec
8
+ end
@@ -0,0 +1,45 @@
1
+ require "rubygems"
2
+ require "spec"
3
+
4
+ class ExampleSuite
5
+ def run
6
+ options = ::Spec::Runner::OptionParser.new.parse(ARGV.dup, STDERR, STDOUT, false)
7
+ $behaviour_runner = options.create_behaviour_runner
8
+
9
+ require_specs
10
+
11
+ puts "Running Example Suite"
12
+ $behaviour_runner.run(ARGV, false)
13
+
14
+ run_rspec_examples
15
+ run_test_unit_examples
16
+ end
17
+
18
+ def require_specs
19
+ exclusions = []
20
+ exclusions << "rspec/"
21
+ exclusions << "test_unit/"
22
+
23
+ Dir["#{dir}/**/*_example.rb"].each do |file|
24
+ unless exclusions.any? {|match| file.include?(match)}
25
+ require file
26
+ end
27
+ end
28
+ end
29
+
30
+ def run_rspec_examples
31
+ system("ruby #{dir}/rspec_example_suite.rb") || raise("Rspec suite Failed")
32
+ end
33
+
34
+ def run_test_unit_examples
35
+ system("ruby #{dir}/test_unit_example_suite.rb") || raise("Test::Unit suite Failed")
36
+ end
37
+
38
+ def dir
39
+ File.dirname(__FILE__)
40
+ end
41
+ end
42
+
43
+ if $0 == __FILE__
44
+ ExampleSuite.new.run
45
+ end
@@ -0,0 +1,132 @@
1
+ dir = File.dirname(__FILE__)
2
+ require "#{dir}/example_helper"
3
+
4
+ describe "RR", :shared => true do
5
+ before(:each) do
6
+ @obj = Object.new
7
+ extend RR::Extensions::DoubleMethods
8
+ end
9
+
10
+ after(:each) do
11
+ RR::Space.instance.reset_doubles
12
+ end
13
+ end
14
+
15
+ describe "RR mock:" do
16
+ it_should_behave_like "RR"
17
+
18
+ it "mocks via inline call" do
19
+ mock(@obj).to_s {"a value"}
20
+ @obj.to_s.should == "a value"
21
+ proc {@obj.to_s}.should raise_error(RR::Expectations::TimesCalledExpectationError)
22
+ end
23
+
24
+ it "allows ordering" do
25
+ mock(@obj).to_s {"value 1"}.ordered
26
+ mock(@obj).to_s {"value 2"}.twice.ordered
27
+ @obj.to_s.should == "value 1"
28
+ @obj.to_s.should == "value 2"
29
+ @obj.to_s.should == "value 2"
30
+ proc {@obj.to_s}.should raise_error(RR::Expectations::TimesCalledExpectationError)
31
+ end
32
+
33
+ it "mocks via block" do
34
+ mock @obj do |c|
35
+ c.to_s {"a value"}
36
+ c.to_sym {:crazy}
37
+ end
38
+ @obj.to_s.should == "a value"
39
+ @obj.to_sym.should == :crazy
40
+ end
41
+
42
+ it "has wildcard matchers" do
43
+ mock(@obj).foobar(
44
+ is_a(String),
45
+ anything,
46
+ numeric,
47
+ boolean,
48
+ duck_type(:to_s),
49
+ /abc/
50
+ ) {"value 1"}.twice
51
+ @obj.foobar(
52
+ 'hello',
53
+ Object.new,
54
+ 99,
55
+ false,
56
+ "My String",
57
+ "Tabcola"
58
+ ).should == "value 1"
59
+ proc {@obj.foobar(:failure)}.should raise_error( RR::ScenarioNotFoundError )
60
+ end
61
+ end
62
+
63
+ describe "RR probe:" do
64
+ it_should_behave_like "RR"
65
+
66
+ it "probes via inline call" do
67
+ expected_to_s_value = @obj.to_s
68
+ probe(@obj).to_s
69
+ @obj.to_s.should == expected_to_s_value
70
+ proc {@obj.to_s}.should raise_error
71
+ end
72
+
73
+ it "allows ordering" do
74
+ def @obj.to_s(arg)
75
+ "Original to_s with arg #{arg}"
76
+ end
77
+ probe(@obj).to_s(:foo).ordered
78
+ probe(@obj).to_s(:bar).twice.ordered
79
+
80
+ @obj.to_s(:foo).should == "Original to_s with arg foo"
81
+ @obj.to_s(:bar).should == "Original to_s with arg bar"
82
+ @obj.to_s(:bar).should == "Original to_s with arg bar"
83
+ proc {@obj.to_s(:bar)}.should raise_error(RR::Expectations::TimesCalledExpectationError)
84
+ end
85
+
86
+ it "probes via block" do
87
+ def @obj.foobar_1(*args)
88
+ :original_value_1
89
+ end
90
+
91
+ def @obj.foobar_2
92
+ :original_value_2
93
+ end
94
+
95
+ probe @obj do |c|
96
+ c.foobar_1(1)
97
+ c.foobar_2
98
+ end
99
+ @obj.foobar_1(1).should == :original_value_1
100
+ proc {@obj.foobar_1(:blah)}.should raise_error
101
+
102
+ @obj.foobar_2.should == :original_value_2
103
+ proc {@obj.foobar_2(:blah)}.should raise_error
104
+ end
105
+ end
106
+
107
+ describe "RR stub:" do
108
+ it_should_behave_like "RR"
109
+
110
+ it "stubs via inline call" do
111
+ stub(@obj).to_s {"a value"}
112
+ @obj.to_s.should == "a value"
113
+ end
114
+
115
+ it "allows ordering" do
116
+ stub(@obj).to_s {"value 1"}.once.ordered
117
+
118
+ stub(@obj).to_s {"value 2"}.once.ordered
119
+
120
+ @obj.to_s.should == "value 1"
121
+ @obj.to_s.should == "value 2"
122
+ end
123
+
124
+ it "stubs via block" do
125
+ stub @obj do |d|
126
+ d.to_s {"a value"}
127
+ d.to_sym {:crazy}
128
+ end
129
+ @obj.to_s.should == "a value"
130
+ @obj.to_sym.should == :crazy
131
+ end
132
+ end
@@ -0,0 +1,90 @@
1
+ dir = File.dirname(__FILE__)
2
+ require "#{dir}/../example_helper"
3
+
4
+ module RR
5
+ describe DoNotAllowCreator, :shared => true do
6
+ before(:each) do
7
+ @space = Space.new
8
+ @subject = Object.new
9
+ end
10
+
11
+ it "initializes creator with passed in object" do
12
+ class << @creator
13
+ attr_reader :subject
14
+ end
15
+ @creator.subject.should === @subject
16
+ end
17
+ end
18
+
19
+ describe DoNotAllowCreator, ".new" do
20
+ it_should_behave_like "RR::DoNotAllowCreator"
21
+
22
+ before do
23
+ @creator = DoNotAllowCreator.new(@space, @subject)
24
+ end
25
+ end
26
+
27
+ describe DoNotAllowCreator, ".new with block" do
28
+ it_should_behave_like "RR::DoNotAllowCreator"
29
+
30
+ before do
31
+ @creator = DoNotAllowCreator.new(@space, @subject) do |c|
32
+ c.any_args
33
+ c.no_args.with_no_args
34
+ c.with_args(1, 2)
35
+ end
36
+ end
37
+
38
+ it "raises TimesCalledExpectationError when any_args is called with no arguments" do
39
+ proc {@subject.any_args}.should raise_error(Expectations::TimesCalledExpectationError)
40
+ end
41
+
42
+ it "raises TimesCalledExpectationError when any_args is called with arguments" do
43
+ proc {@subject.any_args(1, 2)}.should raise_error(Expectations::TimesCalledExpectationError)
44
+ end
45
+
46
+ it "raises TimesCalledExpectationError when no_args is called with no arguments" do
47
+ proc {@subject.no_args}.should raise_error(Expectations::TimesCalledExpectationError)
48
+ end
49
+
50
+ it "does not raise TimesCalledExpectationError when no_args is called with arguments" do
51
+ proc {@subject.no_args(1, 2)}.should raise_error(ScenarioNotFoundError)
52
+ end
53
+
54
+ it "raises TimesCalledExpectationError when any_args is called with no arguments" do
55
+ proc {@subject.with_args}.should raise_error(ScenarioNotFoundError)
56
+ end
57
+
58
+ it "raises TimesCalledExpectationError when any_args is called with arguments" do
59
+ proc {@subject.any_args(1, 2)}.should raise_error(Expectations::TimesCalledExpectationError)
60
+ end
61
+ end
62
+
63
+ describe DoNotAllowCreator, "#method_missing" do
64
+ it_should_behave_like "RR::DoNotAllowCreator"
65
+
66
+ before do
67
+ @subject = Object.new
68
+ @creator = DoNotAllowCreator.new(@space, @subject)
69
+ end
70
+
71
+ it "sets expectation for method to never be called with any arguments when on arguments passed in" do
72
+ @creator.foobar
73
+ proc {@subject.foobar}.should raise_error(Expectations::TimesCalledExpectationError)
74
+ proc {@subject.foobar(1, 2)}.should raise_error(Expectations::TimesCalledExpectationError)
75
+ end
76
+
77
+ it "sets expectation for method to never be called with passed in arguments" do
78
+ @creator.foobar(1, 2)
79
+ proc {@subject.foobar}.should raise_error(ScenarioNotFoundError)
80
+ proc {@subject.foobar(1, 2)}.should raise_error(Expectations::TimesCalledExpectationError)
81
+ end
82
+
83
+ it "sets expectation for method to never be called with no arguments when with_no_args is set" do
84
+ @creator.foobar.with_no_args
85
+ proc {@subject.foobar}.should raise_error(Expectations::TimesCalledExpectationError)
86
+ proc {@subject.foobar(1, 2)}.should raise_error(ScenarioNotFoundError)
87
+ end
88
+ end
89
+
90
+ end
@@ -0,0 +1,32 @@
1
+ dir = File.dirname(__FILE__)
2
+ require "#{dir}/../example_helper"
3
+
4
+ module RR
5
+ describe Double, "#bind with an existing method" do
6
+ before do
7
+ @space = Space.new
8
+ @object = Object.new
9
+ @method_name = :foobar
10
+ def @object.foobar; :original_foobar; end
11
+ @object.methods.should include(@method_name.to_s)
12
+ @double = Double.new(@space, @object, @method_name)
13
+ end
14
+
15
+ it "overrides the original method with the double's dispatching methods" do
16
+ @object.respond_to?(:__rr__foobar__rr__).should == false
17
+ @double.bind
18
+ @object.respond_to?(:__rr__foobar__rr__).should == true
19
+
20
+ rr_foobar_called = false
21
+ (class << @object; self; end).class_eval do
22
+ define_method :__rr__foobar__rr__ do
23
+ rr_foobar_called = true
24
+ end
25
+ end
26
+
27
+ rr_foobar_called.should == false
28
+ @object.foobar
29
+ rr_foobar_called.should == true
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,167 @@
1
+ dir = File.dirname(__FILE__)
2
+ require "#{dir}/../example_helper"
3
+
4
+ module RR
5
+ describe Double, "method dispatching", :shared => true do
6
+ before do
7
+ @space = Space.new
8
+ @object = Object.new
9
+ @method_name = :foobar
10
+ @object.methods.should_not include(@method_name.to_s)
11
+ @double = @space.create_double(@object, @method_name)
12
+ end
13
+ end
14
+
15
+ describe Double, " method dispatching where the scenario takes a block" do
16
+ it_should_behave_like "RR::Double method dispatching"
17
+
18
+ it "executes the block" do
19
+ method_fixture = Object.new
20
+ class << method_fixture
21
+ def method_with_block(a, b)
22
+ yield(a,b)
23
+ end
24
+ end
25
+ scenario = @space.create_scenario(@double)
26
+ scenario.with(1, 2).implemented_by(method_fixture.method(:method_with_block))
27
+ @object.foobar(1, 2) {|a, b| [b, a]}.should == [2, 1]
28
+ end
29
+ end
30
+
31
+ describe Double, " method dispatching where there are no scenarios with duplicate ArgumentExpectations" do
32
+ it_should_behave_like "RR::Double method dispatching"
33
+
34
+ it "dispatches to Scenario that have an exact match" do
35
+ scenario1_with_exact_match = @space.create_scenario(@double)
36
+ scenario1_with_exact_match.with(:exact_match_1).returns {:return_1}
37
+ scenario_with_no_match = @space.create_scenario(@double)
38
+ scenario_with_no_match.with("nothing that matches").returns {:no_match}
39
+ scenario2_with_exact_match = @space.create_scenario(@double)
40
+ scenario2_with_exact_match.with(:exact_match_2).returns {:return_2}
41
+
42
+ @object.foobar(:exact_match_1).should == :return_1
43
+ @object.foobar(:exact_match_2).should == :return_2
44
+ end
45
+
46
+ it "dispatches to Scenario that have a wildcard match" do
47
+ scenario_with_wildcard_match = @space.create_scenario(@double)
48
+ scenario_with_wildcard_match.with_any_args.returns {:wild_card_value}
49
+ scenario_with_no_match = @space.create_scenario(@double)
50
+ scenario_with_no_match.with("nothing that matches").returns {:no_match}
51
+
52
+ @object.foobar(:wildcard_match_1).should == :wild_card_value
53
+ @object.foobar(:wildcard_match_2, 3).should == :wild_card_value
54
+ end
55
+ end
56
+
57
+ describe Double, " method dispatching where there are scenarios" do
58
+ it_should_behave_like "RR::Double method dispatching"
59
+
60
+ it "raises ScenarioNotFoundError error when arguments do not match a scenario" do
61
+ scenario_1 = @space.create_scenario(@double)
62
+ scenario_1.with(1, 2)
63
+
64
+ scenario_2 = @space.create_scenario(@double)
65
+ scenario_2.with(3)
66
+
67
+ proc {@object.foobar(:no_matching_args)}.should raise_error(
68
+ ScenarioNotFoundError,
69
+ "No scenario for arguments [:no_matching_args]"
70
+ )
71
+ end
72
+ end
73
+
74
+ describe Double, " method dispatching where there are scenarios with duplicate Exact Match ArgumentExpectations" do
75
+ it_should_behave_like "RR::Double method dispatching"
76
+
77
+ it "dispatches to Scenario that have an exact match" do
78
+ scenario1_with_exact_match = @space.create_scenario(@double)
79
+ scenario1_with_exact_match.with(:exact_match).returns {:return_1}
80
+
81
+ @object.foobar(:exact_match).should == :return_1
82
+ end
83
+
84
+ it "dispatches to the first Scenario that have an exact match" do
85
+ scenario1_with_exact_match = @space.create_scenario(@double)
86
+ scenario1_with_exact_match.with(:exact_match).returns {:return_1}
87
+
88
+ scenario2_with_exact_match = @space.create_scenario(@double)
89
+ scenario2_with_exact_match.with(:exact_match).returns {:return_2}
90
+
91
+ @object.foobar(:exact_match).should == :return_1
92
+ end
93
+
94
+ it "dispatches the second Scenario with an exact match
95
+ when the first scenario's Times Called expectation is satisfied" do
96
+ scenario1_with_exact_match = @space.create_scenario(@double)
97
+ scenario1_with_exact_match.with(:exact_match).returns {:return_1}.once
98
+
99
+ scenario2_with_exact_match = @space.create_scenario(@double)
100
+ scenario2_with_exact_match.with(:exact_match).returns {:return_2}.once
101
+
102
+ @object.foobar(:exact_match)
103
+ @object.foobar(:exact_match).should == :return_2
104
+ end
105
+
106
+ it "raises TimesCalledExpectationError when all of the scenarios Times Called expectation is satisfied" do
107
+ scenario1_with_exact_match = @space.create_scenario(@double)
108
+ scenario1_with_exact_match.with(:exact_match).returns {:return_1}.once
109
+
110
+ scenario2_with_exact_match = @space.create_scenario(@double)
111
+ scenario2_with_exact_match.with(:exact_match).returns {:return_2}.once
112
+
113
+ @object.foobar(:exact_match)
114
+ @object.foobar(:exact_match)
115
+ proc do
116
+ @object.foobar(:exact_match)
117
+ end.should raise_error(Expectations::TimesCalledExpectationError)
118
+ end
119
+ end
120
+
121
+ describe Double, " method dispatching where there are scenarios with duplicate Wildcard Match ArgumentExpectations" do
122
+ it_should_behave_like "RR::Double method dispatching"
123
+
124
+ it "dispatches to Scenario that have a wildcard match" do
125
+ scenario_1 = @space.create_scenario(@double)
126
+ scenario_1.with_any_args.returns {:return_1}
127
+
128
+ @object.foobar(:anything).should == :return_1
129
+ end
130
+
131
+ it "dispatches to the first Scenario that has a wildcard match" do
132
+ scenario_1 = @space.create_scenario(@double)
133
+ scenario_1.with_any_args.returns {:return_1}
134
+
135
+ scenario_2 = @space.create_scenario(@double)
136
+ scenario_2.with_any_args.returns {:return_2}
137
+
138
+ @object.foobar(:anything).should == :return_1
139
+ end
140
+
141
+ it "dispatches the second Scenario with a wildcard match
142
+ when the first scenario's Times Called expectation is satisfied" do
143
+ scenario_1 = @space.create_scenario(@double)
144
+ scenario_1.with_any_args.returns {:return_1}.once
145
+
146
+ scenario_2 = @space.create_scenario(@double)
147
+ scenario_2.with_any_args.returns {:return_2}.once
148
+
149
+ @object.foobar(:anything)
150
+ @object.foobar(:anything).should == :return_2
151
+ end
152
+
153
+ it "raises TimesCalledExpectationError when all of the scenarios Times Called expectation is satisfied" do
154
+ scenario_1 = @space.create_scenario(@double)
155
+ scenario_1.with_any_args.returns {:return_1}.once
156
+
157
+ scenario_2 = @space.create_scenario(@double)
158
+ scenario_2.with_any_args.returns {:return_2}.once
159
+
160
+ @object.foobar(:anything)
161
+ @object.foobar(:anything)
162
+ proc do
163
+ @object.foobar(:anything)
164
+ end.should raise_error(Expectations::TimesCalledExpectationError)
165
+ end
166
+ end
167
+ end