rr 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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