rr 0.4.10 → 0.6.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 (110) hide show
  1. data/CHANGES +14 -0
  2. data/README.rdoc +67 -13
  3. data/Rakefile +1 -1
  4. data/lib/rr.rb +29 -9
  5. data/lib/rr/adapters/rr_methods.rb +38 -158
  6. data/lib/rr/double.rb +46 -41
  7. data/lib/rr/double_definitions/child_double_definition_creator.rb +23 -0
  8. data/lib/rr/double_definitions/double_definition.rb +212 -0
  9. data/lib/rr/double_definitions/double_definition_creator.rb +153 -0
  10. data/lib/rr/double_definitions/double_definition_creator_proxy.rb +25 -0
  11. data/lib/rr/double_definitions/strategies/implementation/implementation_strategy.rb +15 -0
  12. data/lib/rr/double_definitions/strategies/implementation/proxy.rb +62 -0
  13. data/lib/rr/double_definitions/strategies/implementation/reimplementation.rb +14 -0
  14. data/lib/rr/double_definitions/strategies/scope/instance.rb +15 -0
  15. data/lib/rr/double_definitions/strategies/scope/instance_of_class.rb +43 -0
  16. data/lib/rr/double_definitions/strategies/scope/scope_strategy.rb +15 -0
  17. data/lib/rr/double_definitions/strategies/strategy.rb +70 -0
  18. data/lib/rr/double_definitions/strategies/verification/dont_allow.rb +34 -0
  19. data/lib/rr/double_definitions/strategies/verification/mock.rb +44 -0
  20. data/lib/rr/double_definitions/strategies/verification/stub.rb +45 -0
  21. data/lib/rr/double_definitions/strategies/verification/verification_strategy.rb +15 -0
  22. data/lib/rr/double_injection.rb +21 -15
  23. data/lib/rr/expectations/argument_equality_expectation.rb +2 -1
  24. data/lib/rr/space.rb +23 -22
  25. data/lib/rr/wildcard_matchers/hash_including.rb +29 -0
  26. data/lib/rr/wildcard_matchers/satisfy.rb +26 -0
  27. data/spec/high_level_spec.rb +111 -64
  28. data/spec/rr/adapters/rr_methods_argument_matcher_spec.rb +1 -1
  29. data/spec/rr/adapters/rr_methods_creator_spec.rb +99 -315
  30. data/spec/rr/adapters/rr_methods_space_spec.rb +90 -109
  31. data/spec/rr/adapters/rr_methods_spec_helper.rb +1 -1
  32. data/spec/rr/adapters/rr_methods_times_matcher_spec.rb +1 -1
  33. data/spec/rr/double_definitions/child_double_definition_creator_spec.rb +103 -0
  34. data/spec/rr/double_definitions/double_definition_creator_proxy_spec.rb +83 -0
  35. data/spec/rr/double_definitions/double_definition_creator_spec.rb +495 -0
  36. data/spec/rr/double_definitions/double_definition_spec.rb +1116 -0
  37. data/spec/rr/double_injection/double_injection_bind_spec.rb +111 -0
  38. data/spec/rr/double_injection/double_injection_dispatching_spec.rb +245 -0
  39. data/spec/rr/{double → double_injection}/double_injection_has_original_method_spec.rb +9 -9
  40. data/spec/rr/double_injection/double_injection_reset_spec.rb +90 -0
  41. data/spec/rr/double_injection/double_injection_spec.rb +77 -0
  42. data/spec/rr/double_injection/double_injection_verify_spec.rb +29 -0
  43. data/spec/rr/double_spec.rb +156 -136
  44. data/spec/rr/errors/rr_error_spec.rb +1 -1
  45. data/spec/rr/expectations/any_argument_expectation_spec.rb +1 -1
  46. data/spec/rr/expectations/anything_argument_equality_expectation_spec.rb +6 -30
  47. data/spec/rr/expectations/argument_equality_expectation_spec.rb +35 -18
  48. data/spec/rr/expectations/boolean_argument_equality_expectation_spec.rb +22 -41
  49. data/spec/rr/expectations/hash_including_argument_equality_expectation_spec.rb +82 -0
  50. data/spec/rr/expectations/hash_including_spec.rb +17 -0
  51. data/spec/rr/expectations/satisfy_argument_equality_expectation_spec.rb +59 -0
  52. data/spec/rr/expectations/satisfy_spec.rb +14 -0
  53. data/spec/rr/expectations/times_called_expectation/times_called_expectation_any_times_spec.rb +30 -28
  54. data/spec/rr/expectations/times_called_expectation/times_called_expectation_at_least_spec.rb +55 -54
  55. data/spec/rr/expectations/times_called_expectation/times_called_expectation_at_most_spec.rb +49 -48
  56. data/spec/rr/expectations/times_called_expectation/times_called_expectation_helper.rb +9 -7
  57. data/spec/rr/expectations/times_called_expectation/times_called_expectation_integer_spec.rb +77 -76
  58. data/spec/rr/expectations/times_called_expectation/times_called_expectation_proc_spec.rb +58 -57
  59. data/spec/rr/expectations/times_called_expectation/times_called_expectation_range_spec.rb +59 -58
  60. data/spec/rr/expectations/times_called_expectation/times_called_expectation_spec.rb +25 -24
  61. data/spec/rr/rspec/rspec_adapter_spec.rb +12 -11
  62. data/spec/rr/rspec/rspec_backtrace_tweaking_spec.rb +10 -8
  63. data/spec/rr/rspec/rspec_usage_spec.rb +1 -1
  64. data/spec/rr/space/hash_with_object_id_key_spec.rb +1 -1
  65. data/spec/rr/space/space_spec.rb +330 -192
  66. data/spec/rr/test_unit/test_helper.rb +1 -2
  67. data/spec/rr/test_unit/test_unit_backtrace_test.rb +1 -2
  68. data/spec/rr/test_unit/test_unit_integration_test.rb +1 -2
  69. data/spec/rr/times_called_matchers/any_times_matcher_spec.rb +1 -1
  70. data/spec/rr/times_called_matchers/at_least_matcher_spec.rb +1 -1
  71. data/spec/rr/times_called_matchers/at_most_matcher_spec.rb +1 -1
  72. data/spec/rr/times_called_matchers/integer_matcher_spec.rb +1 -1
  73. data/spec/rr/times_called_matchers/proc_matcher_spec.rb +1 -1
  74. data/spec/rr/times_called_matchers/range_matcher_spec.rb +1 -1
  75. data/spec/rr/times_called_matchers/times_called_matcher_spec.rb +1 -1
  76. data/spec/rr/wildcard_matchers/anything_spec.rb +24 -0
  77. data/spec/rr/wildcard_matchers/boolean_spec.rb +36 -0
  78. data/spec/rr/wildcard_matchers/duck_type_spec.rb +52 -0
  79. data/spec/rr/wildcard_matchers/is_a_spec.rb +32 -0
  80. data/spec/rr/wildcard_matchers/numeric_spec.rb +32 -0
  81. data/spec/rr/wildcard_matchers/range_spec.rb +35 -0
  82. data/spec/rr/wildcard_matchers/regexp_spec.rb +43 -0
  83. data/spec/rr_spec.rb +28 -0
  84. data/spec/spec_helper.rb +84 -0
  85. metadata +43 -29
  86. data/lib/rr/double_creator.rb +0 -271
  87. data/lib/rr/double_definition.rb +0 -179
  88. data/lib/rr/double_definition_builder.rb +0 -44
  89. data/lib/rr/double_definition_creator.rb +0 -156
  90. data/lib/rr/double_definition_creator_proxy.rb +0 -20
  91. data/spec/rr/double/double_injection_bind_spec.rb +0 -105
  92. data/spec/rr/double/double_injection_dispatching_spec.rb +0 -228
  93. data/spec/rr/double/double_injection_reset_spec.rb +0 -86
  94. data/spec/rr/double/double_injection_spec.rb +0 -72
  95. data/spec/rr/double/double_injection_verify_spec.rb +0 -24
  96. data/spec/rr/double_definition_creator_proxy_spec.rb +0 -85
  97. data/spec/rr/double_definition_creator_spec.rb +0 -496
  98. data/spec/rr/double_definition_spec.rb +0 -815
  99. data/spec/rr/expectations/anything_spec.rb +0 -14
  100. data/spec/rr/expectations/boolean_spec.rb +0 -14
  101. data/spec/rr/expectations/duck_type_argument_equality_expectation_spec.rb +0 -71
  102. data/spec/rr/expectations/duck_type_spec.rb +0 -14
  103. data/spec/rr/expectations/is_a_argument_equality_expectation_spec.rb +0 -51
  104. data/spec/rr/expectations/is_a_spec.rb +0 -14
  105. data/spec/rr/expectations/numeric_argument_equality_expectation_spec.rb +0 -47
  106. data/spec/rr/expectations/numeric_spec.rb +0 -14
  107. data/spec/rr/expectations/range_argument_equality_expectation_spec.rb +0 -59
  108. data/spec/rr/expectations/range_spec.rb +0 -10
  109. data/spec/rr/expectations/regexp_argument_equality_expectation_spec.rb +0 -72
  110. data/spec/rr/expectations/regexp_spec.rb +0 -10
@@ -1,134 +1,115 @@
1
- require "spec/spec_helper"
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper")
2
2
 
3
3
  module RR
4
4
  module Adapters
5
- describe RRMethods, " Space interactions" do
6
- describe RRMethods, " space example" do
7
- it_should_behave_like "RR::Adapters::RRMethods"
8
- before do
9
- @old_space = Space.instance
10
-
11
- @space = Space.new
12
- Space.instance = @space
13
- @object1 = Object.new
14
- @object2 = Object.new
15
- @method_name = :foobar
16
- end
5
+ describe RRMethods do
6
+ attr_reader :space, :subject_1, :subject_2, :method_name
7
+ it_should_behave_like "Swapped Space"
8
+ it_should_behave_like "RR::Adapters::RRMethods"
9
+ before do
10
+ @subject_1 = Object.new
11
+ @subject_2 = Object.new
12
+ @method_name = :foobar
13
+ end
17
14
 
18
- after do
19
- Space.instance = @old_space
15
+ describe "#verify" do
16
+ it "aliases #rr_verify" do
17
+ RRMethods.instance_method("verify").should == RRMethods.instance_method("rr_verify")
20
18
  end
21
-
22
- describe RRMethods, "#verify" do
23
- it "#verify verifies and deletes the double_injections" do
24
- verifies_all_double_injections {verify}
25
- end
26
-
27
- it "#rr_verify verifies and deletes the double_injections" do
28
- verifies_all_double_injections {rr_verify}
29
- end
19
+ end
30
20
 
31
- def verifies_all_double_injections
32
- double1 = @space.double_injection(@object1, @method_name)
33
- double1_verify_calls = 0
34
- double1_reset_calls = 0
35
- (
36
- class << double1;
37
- self;
38
- end).class_eval do
39
- define_method(:verify) do ||
40
- double1_verify_calls += 1
41
- end
42
- define_method(:reset) do ||
43
- double1_reset_calls += 1
44
- end
21
+ describe "#rr_verify" do
22
+ it "verifies and deletes the double_injections" do
23
+ double_1 = space.double_injection(subject_1, method_name)
24
+ double_1_verify_calls = 0
25
+ double_1_reset_calls = 0
26
+ (
27
+ class << double_1;
28
+ self;
29
+ end).class_eval do
30
+ define_method(:verify) do ||
31
+ double_1_verify_calls += 1
45
32
  end
46
- double2 = @space.double_injection(@object2, @method_name)
47
- double2_verify_calls = 0
48
- double2_reset_calls = 0
49
- (
50
- class << double2;
51
- self;
52
- end).class_eval do
53
- define_method(:verify) do ||
54
- double2_verify_calls += 1
55
- end
56
- define_method(:reset) do ||
57
- double2_reset_calls += 1
58
- end
33
+ define_method(:reset) do ||
34
+ double_1_reset_calls += 1
59
35
  end
60
-
61
- yield
62
- double1_verify_calls.should == 1
63
- double2_verify_calls.should == 1
64
- double1_reset_calls.should == 1
65
- double1_reset_calls.should == 1
66
- end
67
- end
68
-
69
- describe RRMethods, "#reset" do
70
- it "#reset removes the ordered doubles" do
71
- removes_ordered_doubles {reset}
72
36
  end
73
-
74
- it "#rr_reset removes the ordered doubles" do
75
- removes_ordered_doubles {rr_reset}
76
- end
77
-
78
- it "#reset resets all double_injections" do
79
- resets_all_double_injections {reset}
37
+ double_2 = space.double_injection(subject_2, method_name)
38
+ double_2_verify_calls = 0
39
+ double_2_reset_calls = 0
40
+ (
41
+ class << double_2;
42
+ self;
43
+ end).class_eval do
44
+ define_method(:verify) do ||
45
+ double_2_verify_calls += 1
46
+ end
47
+ define_method(:reset) do ||
48
+ double_2_reset_calls += 1
49
+ end
80
50
  end
81
51
 
82
- it "#rr_reset resets all double_injections" do
83
- resets_all_double_injections {rr_reset}
84
- end
52
+ rr_verify
53
+ double_1_verify_calls.should == 1
54
+ double_2_verify_calls.should == 1
55
+ double_1_reset_calls.should == 1
56
+ double_1_reset_calls.should == 1
57
+ end
58
+ end
85
59
 
86
- def removes_ordered_doubles
87
- double1 = @space.double_injection(@object1, :foobar1)
88
- double2 = @space.double_injection(@object1, :foobar2)
60
+ describe "#reset" do
61
+ it "aliases #rr_reset" do
62
+ RRMethods.instance_method("reset").should == RRMethods.instance_method("rr_reset")
63
+ end
64
+ end
89
65
 
90
- double1 = Double.new(double1)
91
- double2 = Double.new(double2)
66
+ describe "#rr_reset" do
67
+ it "removes the ordered doubles" do
68
+ double_1 = new_double(
69
+ space.double_injection(subject_1, :foobar1),
70
+ RR::DoubleDefinitions::DoubleDefinition.new(creator = RR::DoubleDefinitions::DoubleDefinitionCreator.new, subject_1)
71
+ )
72
+ double_2 = new_double(
73
+ space.double_injection(subject_2, :foobar2),
74
+ RR::DoubleDefinitions::DoubleDefinition.new(creator = RR::DoubleDefinitions::DoubleDefinitionCreator.new, subject_2)
75
+ )
92
76
 
93
- double1.ordered
94
- double2.ordered
77
+ double_1.ordered
78
+ double_2.ordered
95
79
 
96
- @space.ordered_doubles.should_not be_empty
80
+ space.ordered_doubles.should_not be_empty
97
81
 
98
- yield
99
- @space.ordered_doubles.should be_empty
100
- end
82
+ rr_reset
83
+ space.ordered_doubles.should be_empty
84
+ end
101
85
 
102
- def resets_all_double_injections
103
- double1 = @space.double_injection(@object1, @method_name)
104
- double1_reset_calls = 0
105
- (
106
- class << double1;
107
- self;
108
- end).class_eval do
109
- define_method(:reset) do ||
110
- double1_reset_calls += 1
111
- end
86
+ it "resets all double_injections" do
87
+ double_1 = space.double_injection(subject_1, method_name)
88
+ double_1_reset_calls = 0
89
+ (
90
+ class << double_1;
91
+ self;
92
+ end).class_eval do
93
+ define_method(:reset) do ||
94
+ double_1_reset_calls += 1
112
95
  end
113
- double2 = @space.double_injection(@object2, @method_name)
114
- double2_reset_calls = 0
115
- (
116
- class << double2;
117
- self;
118
- end).class_eval do
119
- define_method(:reset) do ||
120
- double2_reset_calls += 1
121
- end
96
+ end
97
+ double_2 = space.double_injection(subject_2, method_name)
98
+ double_2_reset_calls = 0
99
+ (
100
+ class << double_2;
101
+ self;
102
+ end).class_eval do
103
+ define_method(:reset) do ||
104
+ double_2_reset_calls += 1
122
105
  end
123
-
124
- yield
125
- double1_reset_calls.should == 1
126
- double2_reset_calls.should == 1
127
106
  end
107
+
108
+ rr_reset
109
+ double_1_reset_calls.should == 1
110
+ double_2_reset_calls.should == 1
128
111
  end
129
112
  end
130
113
  end
131
-
132
-
133
114
  end
134
115
  end
@@ -1,4 +1,4 @@
1
- require "spec/spec_helper"
1
+ # require File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper")
2
2
 
3
3
  module RR
4
4
  module Adapters
@@ -1,4 +1,4 @@
1
- require "spec/spec_helper"
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper")
2
2
 
3
3
  module RR
4
4
  module Adapters
@@ -0,0 +1,103 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper")
2
+
3
+ module RR
4
+ module DoubleDefinitions
5
+ describe ChildDoubleDefinitionCreator do
6
+ attr_reader :parent_subject, :parent_double_definition_creator, :parent_double_definition, :child_double_definition_creator
7
+ it_should_behave_like "Swapped Space"
8
+ before(:each) do
9
+ @parent_subject = Object.new
10
+ @parent_double_definition_creator = DoubleDefinitionCreator.new
11
+ @parent_double_definition = DoubleDefinition.new(parent_double_definition_creator, parent_subject)
12
+ @child_double_definition_creator = ChildDoubleDefinitionCreator.new(parent_double_definition)
13
+ end
14
+
15
+ describe "Strategies::Verification definitions" do
16
+ describe "methods without !" do
17
+ attr_reader :child_subject
18
+ before do
19
+ @child_subject = Object.new
20
+ end
21
+
22
+ describe "#mock" do
23
+ context "when passed a subject" do
24
+ it "sets #parent_double_definition.implementation to a Proc returning the passed-in subject" do
25
+ parent_double_definition.implementation.should be_nil
26
+ child_double_definition_creator.mock(child_subject)
27
+ parent_double_definition.implementation.call.should == child_subject
28
+ end
29
+ end
30
+ end
31
+
32
+ describe "#stub" do
33
+ context "when passed a subject" do
34
+ it "sets #parent_double_definition.implementation to a Proc returning the passed-in subject" do
35
+ parent_double_definition.implementation.should be_nil
36
+ child_double_definition_creator.stub(child_subject)
37
+ parent_double_definition.implementation.call.should == child_subject
38
+ end
39
+ end
40
+ end
41
+
42
+ describe "#dont_allow" do
43
+ context "when passed a subject" do
44
+ it "sets #parent_double_definition.implementation to a Proc returning the passed-in subject" do
45
+ parent_double_definition.implementation.should be_nil
46
+ child_double_definition_creator.dont_allow(child_subject)
47
+ parent_double_definition.implementation.call.should == child_subject
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ describe "methods with !" do
54
+ describe "#mock!" do
55
+ it "sets #parent_double_definition.implementation to a Proc returning the #subject" do
56
+ parent_double_definition.implementation.should be_nil
57
+ child_subject = child_double_definition_creator.mock!.__creator__.subject
58
+ parent_double_definition.implementation.call.should == child_subject
59
+ end
60
+ end
61
+
62
+ describe "#stub!" do
63
+ it "sets #parent_double_definition.implementation to a Proc returning the #subject" do
64
+ parent_double_definition.implementation.should be_nil
65
+ child_subject = child_double_definition_creator.stub!.__creator__.subject
66
+ parent_double_definition.implementation.call.should == child_subject
67
+ end
68
+ end
69
+
70
+ describe "#dont_allow!" do
71
+ it "sets #parent_double_definition.implementation to a Proc returning the #subject" do
72
+ parent_double_definition.implementation.should be_nil
73
+ child_subject = child_double_definition_creator.dont_allow!.__creator__.subject
74
+ parent_double_definition.implementation.call.should == child_subject
75
+ end
76
+ end
77
+ end
78
+ end
79
+
80
+ describe "Strategies::Scope definitions" do
81
+ describe "methods without !" do
82
+ describe "#instance_of" do
83
+ it "raises a NoMethodError" do
84
+ lambda do
85
+ child_double_definition_creator.instance_of
86
+ end.should raise_error(NoMethodError)
87
+ end
88
+ end
89
+ end
90
+
91
+ describe "methods with !" do
92
+ describe "#instance_of!" do
93
+ it "raises a NoMethodError" do
94
+ lambda do
95
+ child_double_definition_creator.instance_of!
96
+ end.should raise_error(NoMethodError)
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,83 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper")
2
+
3
+ module RR
4
+ module DoubleDefinitions
5
+ describe DoubleDefinitionCreatorProxy do
6
+ attr_reader :subject, :creator, :the_proxy
7
+ it_should_behave_like "Swapped Space"
8
+
9
+ before(:each) do
10
+ @subject = Object.new
11
+ @creator = DoubleDefinitionCreator.new
12
+ creator.mock(subject)
13
+ end
14
+
15
+ macro("initializes proxy with passed in creator") do
16
+ it "initializes proxy with passed in creator" do
17
+ class << the_proxy
18
+ attr_reader :creator
19
+ end
20
+ the_proxy.creator.should === creator
21
+ end
22
+ end
23
+
24
+ describe ".new" do
25
+ it "does not undefine object_id" do
26
+ the_proxy = DoubleDefinitionCreatorProxy.new(creator)
27
+ the_proxy.object_id.class.should == Fixnum
28
+ end
29
+
30
+ context "without block" do
31
+ before do
32
+ @the_proxy = DoubleDefinitionCreatorProxy.new(creator)
33
+ end
34
+
35
+ send "initializes proxy with passed in creator"
36
+
37
+ it "clears out all methods from proxy" do
38
+ proxy_subclass = Class.new(DoubleDefinitionCreatorProxy) do
39
+ def i_should_be_a_double
40
+ end
41
+ end
42
+ proxy_subclass.instance_methods.map {|m| m.to_s}.should include('i_should_be_a_double')
43
+
44
+ proxy = proxy_subclass.new(creator)
45
+ proxy.i_should_be_a_double.should be_instance_of(DoubleDefinition)
46
+ end
47
+ end
48
+
49
+ context "with block" do
50
+ before do
51
+ @the_proxy = DoubleDefinitionCreatorProxy.new(creator) do |b|
52
+ b.foobar(1, 2) {:one_two}
53
+ b.foobar(1) {:one}
54
+ b.foobar.with_any_args {:default}
55
+ b.baz() {:baz_result}
56
+ end
57
+ end
58
+
59
+ send "initializes proxy with passed in creator"
60
+
61
+ it "creates double_injections" do
62
+ subject.foobar(1, 2).should == :one_two
63
+ subject.foobar(1).should == :one
64
+ subject.foobar(:something).should == :default
65
+ subject.baz.should == :baz_result
66
+ end
67
+
68
+ it "clears out all methods from proxy" do
69
+ proxy_subclass = Class.new(DoubleDefinitionCreatorProxy) do
70
+ def i_should_be_a_double
71
+ end
72
+ end
73
+ proxy_subclass.instance_methods.map {|m| m.to_s}.should include('i_should_be_a_double')
74
+
75
+ proxy_subclass.new(creator) do |m|
76
+ m.i_should_be_a_double.should be_instance_of(DoubleDefinition)
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,495 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper")
2
+
3
+ module RR
4
+ module DoubleDefinitions
5
+ describe DoubleDefinitionCreator do
6
+ attr_reader :creator, :subject, :strategy_method_name
7
+ it_should_behave_like "Swapped Space"
8
+ before(:each) do
9
+ @subject = Object.new
10
+ @creator = DoubleDefinitionCreator.new
11
+ end
12
+
13
+ describe "StrategySetupMethods" do
14
+ describe "normal strategy definitions" do
15
+ def call_strategy(*args, &block)
16
+ creator.__send__(strategy_method_name, *args, &block)
17
+ end
18
+
19
+ describe "#mock" do
20
+ before do
21
+ @strategy_method_name = :mock
22
+ end
23
+
24
+ send("normal strategy definition")
25
+
26
+ context "when passing no args" do
27
+ it "returns self" do
28
+ call_strategy.should === creator
29
+ end
30
+ end
31
+
32
+ context "when passed a subject and a method_name argument" do
33
+ it "creates a mock Double for method" do
34
+ double_definition = creator.mock(subject, :foobar).returns {:baz}
35
+ double_definition.times_matcher.should == TimesCalledMatchers::IntegerMatcher.new(1)
36
+ double_definition.argument_expectation.class.should == RR::Expectations::ArgumentEqualityExpectation
37
+ double_definition.argument_expectation.expected_arguments.should == []
38
+ subject.foobar.should == :baz
39
+ end
40
+ end
41
+
42
+ context "when already using an ImplementationStrategy" do
43
+ it "raises a DoubleDefinitionError" do
44
+ creator.mock
45
+ lambda do
46
+ call_strategy
47
+ end.should raise_error(RR::Errors::DoubleDefinitionError, "This Double already has a mock strategy")
48
+ end
49
+ end
50
+ end
51
+
52
+ describe "#stub" do
53
+ before do
54
+ @strategy_method_name = :stub
55
+ end
56
+
57
+ send("normal strategy definition")
58
+
59
+ context "when passing no args" do
60
+ it "returns self" do
61
+ call_strategy.should === creator
62
+ end
63
+ end
64
+
65
+ context "when passed subject and a method_name argument" do
66
+ it "creates a stub Double for method when passed a method_name argument" do
67
+ double_definition = creator.stub(subject, :foobar).returns {:baz}
68
+ double_definition.times_matcher.should == TimesCalledMatchers::AnyTimesMatcher.new
69
+ double_definition.argument_expectation.class.should == RR::Expectations::AnyArgumentExpectation
70
+ subject.foobar.should == :baz
71
+ end
72
+ end
73
+
74
+ context "when already using an ImplementationStrategy" do
75
+ it "raises a DoubleDefinitionError" do
76
+ creator.mock
77
+ lambda do
78
+ call_strategy
79
+ end.should raise_error(RR::Errors::DoubleDefinitionError, "This Double already has a mock strategy")
80
+ end
81
+ end
82
+ end
83
+
84
+ describe "#dont_allow" do
85
+ before do
86
+ @strategy_method_name = :dont_allow
87
+ end
88
+
89
+ send("normal strategy definition")
90
+
91
+ context "when passing no args" do
92
+ it "returns self" do
93
+ call_strategy.should === creator
94
+ end
95
+ end
96
+
97
+ it "raises error when proxied" do
98
+ creator.proxy
99
+ lambda do
100
+ creator.dont_allow
101
+ end.should raise_error(Errors::DoubleDefinitionError, "Doubles cannot be proxied when using dont_allow strategy")
102
+ end
103
+
104
+ context "when passed a subject and a method_name argument_expectation" do
105
+ it "creates a mock Double for method" do
106
+ double_definition = creator.dont_allow(subject, :foobar)
107
+ double_definition.times_matcher.should == TimesCalledMatchers::IntegerMatcher.new(0)
108
+ double_definition.argument_expectation.class.should == RR::Expectations::AnyArgumentExpectation
109
+
110
+ lambda do
111
+ subject.foobar
112
+ end.should raise_error(Errors::TimesCalledError)
113
+ RR.reset
114
+ end
115
+ end
116
+
117
+ context "when already using an ImplementationStrategy" do
118
+ it "raises a DoubleDefinitionError" do
119
+ creator.mock
120
+ lambda do
121
+ call_strategy
122
+ end.should raise_error(RR::Errors::DoubleDefinitionError, "This Double already has a mock strategy")
123
+ end
124
+ end
125
+ end
126
+ end
127
+
128
+ describe "! strategy definitions" do
129
+ attr_reader :strategy_method_name
130
+ def call_strategy(*args, &definition_eval_block)
131
+ creator.__send__(strategy_method_name, *args, &definition_eval_block)
132
+ end
133
+
134
+ describe "#mock!" do
135
+ before do
136
+ @strategy_method_name = :mock!
137
+ end
138
+
139
+ send("! strategy definition")
140
+
141
+ context "when passed a method_name argument" do
142
+ it "sets #verification_strategy to Mock" do
143
+ creator.mock!(:foobar)
144
+ creator.verification_strategy.class.should == Strategies::Verification::Mock
145
+ end
146
+ end
147
+ end
148
+
149
+ describe "#stub!" do
150
+ before do
151
+ @strategy_method_name = :stub!
152
+ end
153
+
154
+ send("! strategy definition")
155
+
156
+ context "when passed a method_name argument" do
157
+ it "sets #verification_strategy to Stub" do
158
+ creator.stub!(:foobar)
159
+ creator.verification_strategy.class.should == Strategies::Verification::Stub
160
+ end
161
+ end
162
+ end
163
+
164
+ describe "#dont_allow!" do
165
+ before do
166
+ @strategy_method_name = :dont_allow!
167
+ end
168
+
169
+ send("! strategy definition")
170
+
171
+ context "when passed a method_name argument" do
172
+ it "sets #verification_strategy to DontAllow" do
173
+ creator.dont_allow!(:foobar)
174
+ creator.verification_strategy.class.should == Strategies::Verification::DontAllow
175
+ end
176
+ end
177
+ end
178
+ end
179
+
180
+ describe "#stub.proxy" do
181
+ before do
182
+ class << subject
183
+ def foobar(*args)
184
+ :original_foobar
185
+ end
186
+ end
187
+ end
188
+
189
+ context "when already using Strategies::Verification::DontAllow" do
190
+ it "raises error" do
191
+ creator.dont_allow
192
+ lambda do
193
+ creator.proxy
194
+ end.should raise_error(Errors::DoubleDefinitionError, "Doubles cannot be proxied when using dont_allow strategy")
195
+ end
196
+ end
197
+
198
+ context "when passed a method_name argument" do
199
+ it "creates a proxy Double for method" do
200
+ double_definition = creator.stub.proxy(subject, :foobar).after_call {:baz}
201
+ double_definition.times_matcher.should == TimesCalledMatchers::AnyTimesMatcher.new
202
+ double_definition.argument_expectation.class.should == RR::Expectations::AnyArgumentExpectation
203
+ subject.foobar.should == :baz
204
+ end
205
+ end
206
+ end
207
+
208
+ describe "#instance_of" do
209
+ context "when not passed a class" do
210
+ it "raises an ArgumentError" do
211
+ lambda do
212
+ creator.instance_of(Object.new)
213
+ end.should raise_error(ArgumentError, "instance_of only accepts class objects")
214
+ end
215
+ end
216
+
217
+ context "when passed a method_name argument" do
218
+ it "creates a proxy Double for method" do
219
+ klass = Class.new
220
+ double_definition = creator.stub.instance_of(klass, :foobar).returns {:baz}
221
+ double_definition.times_matcher.should == TimesCalledMatchers::AnyTimesMatcher.new
222
+ double_definition.argument_expectation.class.should == RR::Expectations::AnyArgumentExpectation
223
+ klass.new.foobar.should == :baz
224
+ end
225
+ end
226
+ end
227
+
228
+ describe "#instance_of.mock" do
229
+ before do
230
+ @klass = Class.new
231
+ end
232
+
233
+ context "when passed no arguments" do
234
+ it "returns a DoubleDefinitionCreator" do
235
+ instance_of.instance_of.should be_instance_of(DoubleDefinitionCreator)
236
+ end
237
+ end
238
+
239
+ context "when passed a method_name argument" do
240
+ it "creates a instance_of Double for method" do
241
+ double_definition = instance_of.mock(@klass, :foobar)
242
+ double_definition.with(1, 2) {:baz}
243
+ double_definition.times_matcher.should == TimesCalledMatchers::IntegerMatcher.new(1)
244
+ double_definition.argument_expectation.class.should == RR::Expectations::ArgumentEqualityExpectation
245
+ double_definition.argument_expectation.expected_arguments.should == [1, 2]
246
+
247
+ @klass.new.foobar(1, 2).should == :baz
248
+ end
249
+ end
250
+ end
251
+ end
252
+
253
+ describe "StrategyExecutionMethods" do
254
+ describe "#create" do
255
+ context "when #verification_strategy is not set" do
256
+ it "raises a DoubleDefinitionError" do
257
+ lambda do
258
+ creator.create(:foobar, 1, 2)
259
+ end.should raise_error(Errors::DoubleDefinitionError, "This Double has no strategy")
260
+ end
261
+ end
262
+
263
+ context "when #verification_strategy is a Mock" do
264
+ context "when #implementation_strategy is a Reimplementation" do
265
+ before do
266
+ creator.mock(subject)
267
+ end
268
+
269
+ it "sets expectation on the #subject that it will be sent the method_name once with the passed-in arguments" do
270
+ creator.create(:foobar, 1, 2)
271
+ subject.foobar(1, 2)
272
+ lambda {subject.foobar(1, 2)}.should raise_error(Errors::TimesCalledError)
273
+ end
274
+
275
+ describe "#subject.method_name being called" do
276
+ it "returns the return value of the Double#returns block" do
277
+ creator.create(:foobar, 1, 2) {:baz}
278
+ subject.foobar(1, 2).should == :baz
279
+ end
280
+ end
281
+ end
282
+
283
+ context "when #implementation_strategy is a Proxy" do
284
+ before do
285
+ creator.mock
286
+ creator.proxy(subject)
287
+ end
288
+
289
+ it "sets expectation on the #subject that it will be sent the method_name once with the passed-in arguments" do
290
+ def subject.foobar(*args)
291
+ :baz;
292
+ end
293
+ creator.create(:foobar, 1, 2)
294
+ subject.foobar(1, 2)
295
+ lambda {subject.foobar(1, 2)}.should raise_error(Errors::TimesCalledError)
296
+ end
297
+
298
+ describe "#subject.method_name being called" do
299
+ it "calls the original method" do
300
+ original_method_called = false
301
+ (class << subject; self; end).class_eval do
302
+ define_method(:foobar) do |*args|
303
+ original_method_called = true
304
+ end
305
+ end
306
+ creator.create(:foobar, 1, 2)
307
+ subject.foobar(1, 2)
308
+ original_method_called.should be_true
309
+ end
310
+
311
+ context "when not passed a block" do
312
+ it "returns the value of the original method" do
313
+ def subject.foobar(*args)
314
+ :baz;
315
+ end
316
+ creator.create(:foobar, 1, 2)
317
+ subject.foobar(1, 2).should == :baz
318
+ end
319
+ end
320
+
321
+ context "when passed a block" do
322
+ attr_reader :real_value
323
+ before do
324
+ @real_value = real_value = Object.new
325
+ (class << subject; self; end).class_eval do
326
+ define_method(:foobar) {real_value}
327
+ end
328
+ end
329
+
330
+ it "calls the block with the return value of the original method" do
331
+ creator.create(:foobar, 1, 2) do |value|
332
+ mock(value).a_method {99}
333
+ value
334
+ end
335
+ subject.foobar(1, 2)
336
+ real_value.a_method.should == 99
337
+ end
338
+
339
+ it "returns the return value of the block" do
340
+ creator.create(:foobar, 1, 2) do |value|
341
+ :something_else
342
+ end
343
+ subject.foobar(1, 2).should == :something_else
344
+ end
345
+ end
346
+ end
347
+ end
348
+ end
349
+
350
+ context "when #verification_strategy is a Stub" do
351
+ context "when #implementation_strategy is a Reimplementation" do
352
+ before do
353
+ creator.stub(subject)
354
+ end
355
+
356
+ context "when not passed a block" do
357
+ it "returns nil" do
358
+ creator.create(:foobar)
359
+ subject.foobar.should be_nil
360
+ end
361
+ end
362
+
363
+ context "when passed a block" do
364
+ describe "#subject.method_name being called" do
365
+ it "returns the return value of the block" do
366
+ creator.create(:foobar) {:baz}
367
+ subject.foobar.should == :baz
368
+ end
369
+ end
370
+ end
371
+
372
+ context "when not passed args" do
373
+ describe "#subject.method_name being called with any arguments" do
374
+ it "invokes the implementation of the Stub" do
375
+ creator.create(:foobar) {:baz}
376
+ subject.foobar(1, 2).should == :baz
377
+ subject.foobar().should == :baz
378
+ subject.foobar([]).should == :baz
379
+ end
380
+ end
381
+ end
382
+
383
+ context "when passed args" do
384
+ describe "#subject.method_name being called with the passed-in arguments" do
385
+ it "invokes the implementation of the Stub" do
386
+ creator.create(:foobar, 1, 2) {:baz}
387
+ subject.foobar(1, 2).should == :baz
388
+ end
389
+ end
390
+
391
+ describe "#subject.method_name being called with different arguments" do
392
+ it "raises a DoubleNotFoundError" do
393
+ creator.create(:foobar, 1, 2) {:baz}
394
+ lambda do
395
+ subject.foobar
396
+ end.should raise_error(Errors::DoubleNotFoundError)
397
+ end
398
+ end
399
+ end
400
+ end
401
+
402
+ context "when #implementation_strategy is a Proxy" do
403
+ before do
404
+ def subject.foobar(*args)
405
+ :original_return_value
406
+ end
407
+ creator.stub
408
+ creator.proxy(subject)
409
+ end
410
+
411
+ context "when not passed a block" do
412
+ describe "#subject.method_name being called" do
413
+ it "invokes the original implementanion" do
414
+ creator.create(:foobar)
415
+ subject.foobar.should == :original_return_value
416
+ end
417
+ end
418
+ end
419
+
420
+ context "when passed a block" do
421
+ describe "#subject.method_name being called" do
422
+ it "invokes the original implementanion and invokes the block with the return value of the original implementanion" do
423
+ passed_in_value = nil
424
+ creator.create(:foobar) do |original_return_value|
425
+ passed_in_value = original_return_value
426
+ end
427
+ subject.foobar
428
+ passed_in_value.should == :original_return_value
429
+ end
430
+
431
+ it "returns the return value of the block" do
432
+ creator.create(:foobar) do |original_return_value|
433
+ :new_return_value
434
+ end
435
+ subject.foobar.should == :new_return_value
436
+ end
437
+ end
438
+ end
439
+
440
+ context "when passed args" do
441
+ describe "#subject.method_name being called with the passed-in arguments" do
442
+ it "invokes the implementation of the Stub" do
443
+ creator.create(:foobar, 1, 2) {:baz}
444
+ subject.foobar(1, 2).should == :baz
445
+ end
446
+ end
447
+
448
+ describe "#subject.method_name being called with different arguments" do
449
+ it "raises a DoubleNotFoundError" do
450
+ creator.create(:foobar, 1, 2) {:baz}
451
+ lambda do
452
+ subject.foobar
453
+ end.should raise_error(Errors::DoubleNotFoundError)
454
+ end
455
+ end
456
+ end
457
+ end
458
+ end
459
+
460
+ context "when #verification_strategy is a DontAllow" do
461
+ before do
462
+ creator.dont_allow(subject)
463
+ end
464
+
465
+ context "when not passed args" do
466
+ describe "#subject.method_name being called with any arguments" do
467
+ it "raises a TimesCalledError" do
468
+ creator.create(:foobar)
469
+ lambda {subject.foobar}.should raise_error(Errors::TimesCalledError)
470
+ lambda {subject.foobar(1, 2)}.should raise_error(Errors::TimesCalledError)
471
+ end
472
+ end
473
+ end
474
+
475
+ context "when passed args" do
476
+ describe "#subject.method_name being called with the passed-in arguments" do
477
+ it "raises a TimesCalledError" do
478
+ creator.create(:foobar, 1, 2)
479
+ lambda {subject.foobar(1, 2)}.should raise_error(Errors::TimesCalledError)
480
+ end
481
+ end
482
+
483
+ describe "#subject.method_name being called with different arguments" do
484
+ it "raises a DoubleNotFoundError" do
485
+ creator.create(:foobar, 1, 2)
486
+ lambda {subject.foobar()}.should raise_error(Errors::DoubleNotFoundError)
487
+ end
488
+ end
489
+ end
490
+ end
491
+ end
492
+ end
493
+ end
494
+ end
495
+ end