jferris-rr 0.7.1.0.1239654108

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 (130) hide show
  1. data/CHANGES +196 -0
  2. data/README.rdoc +329 -0
  3. data/Rakefile +77 -0
  4. data/lib/rr.rb +84 -0
  5. data/lib/rr/adapters/rr_methods.rb +122 -0
  6. data/lib/rr/adapters/rspec.rb +58 -0
  7. data/lib/rr/adapters/test_unit.rb +29 -0
  8. data/lib/rr/double.rb +212 -0
  9. data/lib/rr/double_definitions/child_double_definition_creator.rb +27 -0
  10. data/lib/rr/double_definitions/double_definition.rb +346 -0
  11. data/lib/rr/double_definitions/double_definition_creator.rb +167 -0
  12. data/lib/rr/double_definitions/double_definition_creator_proxy.rb +37 -0
  13. data/lib/rr/double_definitions/strategies/implementation/implementation_strategy.rb +15 -0
  14. data/lib/rr/double_definitions/strategies/implementation/proxy.rb +62 -0
  15. data/lib/rr/double_definitions/strategies/implementation/reimplementation.rb +14 -0
  16. data/lib/rr/double_definitions/strategies/implementation/strongly_typed_reimplementation.rb +17 -0
  17. data/lib/rr/double_definitions/strategies/scope/instance.rb +15 -0
  18. data/lib/rr/double_definitions/strategies/scope/instance_of_class.rb +46 -0
  19. data/lib/rr/double_definitions/strategies/scope/scope_strategy.rb +15 -0
  20. data/lib/rr/double_definitions/strategies/strategy.rb +70 -0
  21. data/lib/rr/double_definitions/strategies/verification/dont_allow.rb +34 -0
  22. data/lib/rr/double_definitions/strategies/verification/mock.rb +44 -0
  23. data/lib/rr/double_definitions/strategies/verification/stub.rb +45 -0
  24. data/lib/rr/double_definitions/strategies/verification/verification_strategy.rb +15 -0
  25. data/lib/rr/double_injection.rb +143 -0
  26. data/lib/rr/double_matches.rb +51 -0
  27. data/lib/rr/errors/argument_equality_error.rb +6 -0
  28. data/lib/rr/errors/double_definition_error.rb +6 -0
  29. data/lib/rr/errors/double_not_found_error.rb +6 -0
  30. data/lib/rr/errors/double_order_error.rb +6 -0
  31. data/lib/rr/errors/rr_error.rb +20 -0
  32. data/lib/rr/errors/spy_verification_errors/double_injection_not_found_error.rb +8 -0
  33. data/lib/rr/errors/spy_verification_errors/invocation_count_error.rb +8 -0
  34. data/lib/rr/errors/spy_verification_errors/spy_verification_error.rb +8 -0
  35. data/lib/rr/errors/subject_does_not_implement_method_error.rb +6 -0
  36. data/lib/rr/errors/subject_has_different_arity_error.rb +6 -0
  37. data/lib/rr/errors/times_called_error.rb +6 -0
  38. data/lib/rr/expectations/any_argument_expectation.rb +21 -0
  39. data/lib/rr/expectations/argument_equality_expectation.rb +41 -0
  40. data/lib/rr/expectations/times_called_expectation.rb +57 -0
  41. data/lib/rr/hash_with_object_id_key.rb +41 -0
  42. data/lib/rr/recorded_calls.rb +103 -0
  43. data/lib/rr/space.rb +123 -0
  44. data/lib/rr/spy_verification.rb +48 -0
  45. data/lib/rr/spy_verification_proxy.rb +18 -0
  46. data/lib/rr/times_called_matchers/any_times_matcher.rb +18 -0
  47. data/lib/rr/times_called_matchers/at_least_matcher.rb +15 -0
  48. data/lib/rr/times_called_matchers/at_most_matcher.rb +23 -0
  49. data/lib/rr/times_called_matchers/integer_matcher.rb +19 -0
  50. data/lib/rr/times_called_matchers/non_terminal.rb +27 -0
  51. data/lib/rr/times_called_matchers/proc_matcher.rb +11 -0
  52. data/lib/rr/times_called_matchers/range_matcher.rb +21 -0
  53. data/lib/rr/times_called_matchers/terminal.rb +20 -0
  54. data/lib/rr/times_called_matchers/times_called_matcher.rb +44 -0
  55. data/lib/rr/wildcard_matchers/anything.rb +18 -0
  56. data/lib/rr/wildcard_matchers/boolean.rb +23 -0
  57. data/lib/rr/wildcard_matchers/duck_type.rb +32 -0
  58. data/lib/rr/wildcard_matchers/hash_including.rb +29 -0
  59. data/lib/rr/wildcard_matchers/is_a.rb +25 -0
  60. data/lib/rr/wildcard_matchers/numeric.rb +13 -0
  61. data/lib/rr/wildcard_matchers/range.rb +7 -0
  62. data/lib/rr/wildcard_matchers/regexp.rb +7 -0
  63. data/lib/rr/wildcard_matchers/satisfy.rb +26 -0
  64. data/spec/core_spec_suite.rb +19 -0
  65. data/spec/environment_fixture_setup.rb +6 -0
  66. data/spec/high_level_spec.rb +368 -0
  67. data/spec/rr/adapters/rr_methods_argument_matcher_spec.rb +67 -0
  68. data/spec/rr/adapters/rr_methods_creator_spec.rb +149 -0
  69. data/spec/rr/adapters/rr_methods_space_spec.rb +115 -0
  70. data/spec/rr/adapters/rr_methods_spec_helper.rb +11 -0
  71. data/spec/rr/adapters/rr_methods_times_matcher_spec.rb +17 -0
  72. data/spec/rr/double_definitions/child_double_definition_creator_spec.rb +112 -0
  73. data/spec/rr/double_definitions/double_definition_creator_proxy_spec.rb +155 -0
  74. data/spec/rr/double_definitions/double_definition_creator_spec.rb +502 -0
  75. data/spec/rr/double_definitions/double_definition_spec.rb +1159 -0
  76. data/spec/rr/double_injection/double_injection_bind_spec.rb +111 -0
  77. data/spec/rr/double_injection/double_injection_dispatching_spec.rb +244 -0
  78. data/spec/rr/double_injection/double_injection_has_original_method_spec.rb +55 -0
  79. data/spec/rr/double_injection/double_injection_reset_spec.rb +90 -0
  80. data/spec/rr/double_injection/double_injection_spec.rb +77 -0
  81. data/spec/rr/double_injection/double_injection_verify_spec.rb +29 -0
  82. data/spec/rr/double_spec.rb +352 -0
  83. data/spec/rr/errors/rr_error_spec.rb +67 -0
  84. data/spec/rr/expectations/any_argument_expectation_spec.rb +47 -0
  85. data/spec/rr/expectations/anything_argument_equality_expectation_spec.rb +14 -0
  86. data/spec/rr/expectations/argument_equality_expectation_spec.rb +135 -0
  87. data/spec/rr/expectations/boolean_argument_equality_expectation_spec.rb +34 -0
  88. data/spec/rr/expectations/hash_including_argument_equality_expectation_spec.rb +82 -0
  89. data/spec/rr/expectations/hash_including_spec.rb +17 -0
  90. data/spec/rr/expectations/satisfy_argument_equality_expectation_spec.rb +59 -0
  91. data/spec/rr/expectations/satisfy_spec.rb +14 -0
  92. data/spec/rr/expectations/times_called_expectation/times_called_expectation_any_times_spec.rb +46 -0
  93. data/spec/rr/expectations/times_called_expectation/times_called_expectation_at_least_spec.rb +69 -0
  94. data/spec/rr/expectations/times_called_expectation/times_called_expectation_at_most_spec.rb +71 -0
  95. data/spec/rr/expectations/times_called_expectation/times_called_expectation_helper.rb +23 -0
  96. data/spec/rr/expectations/times_called_expectation/times_called_expectation_integer_spec.rb +104 -0
  97. data/spec/rr/expectations/times_called_expectation/times_called_expectation_proc_spec.rb +81 -0
  98. data/spec/rr/expectations/times_called_expectation/times_called_expectation_range_spec.rb +83 -0
  99. data/spec/rr/expectations/times_called_expectation/times_called_expectation_spec.rb +38 -0
  100. data/spec/rr/rspec/invocation_matcher_spec.rb +279 -0
  101. data/spec/rr/rspec/rspec_adapter_spec.rb +66 -0
  102. data/spec/rr/rspec/rspec_backtrace_tweaking_spec.rb +31 -0
  103. data/spec/rr/rspec/rspec_backtrace_tweaking_spec_fixture.rb +11 -0
  104. data/spec/rr/rspec/rspec_usage_spec.rb +86 -0
  105. data/spec/rr/space/hash_with_object_id_key_spec.rb +88 -0
  106. data/spec/rr/space/space_spec.rb +542 -0
  107. data/spec/rr/test_unit/test_helper.rb +7 -0
  108. data/spec/rr/test_unit/test_unit_backtrace_test.rb +35 -0
  109. data/spec/rr/test_unit/test_unit_integration_test.rb +57 -0
  110. data/spec/rr/times_called_matchers/any_times_matcher_spec.rb +47 -0
  111. data/spec/rr/times_called_matchers/at_least_matcher_spec.rb +55 -0
  112. data/spec/rr/times_called_matchers/at_most_matcher_spec.rb +70 -0
  113. data/spec/rr/times_called_matchers/integer_matcher_spec.rb +70 -0
  114. data/spec/rr/times_called_matchers/proc_matcher_spec.rb +55 -0
  115. data/spec/rr/times_called_matchers/range_matcher_spec.rb +76 -0
  116. data/spec/rr/times_called_matchers/times_called_matcher_spec.rb +118 -0
  117. data/spec/rr/wildcard_matchers/anything_spec.rb +24 -0
  118. data/spec/rr/wildcard_matchers/boolean_spec.rb +36 -0
  119. data/spec/rr/wildcard_matchers/duck_type_spec.rb +52 -0
  120. data/spec/rr/wildcard_matchers/is_a_spec.rb +32 -0
  121. data/spec/rr/wildcard_matchers/numeric_spec.rb +32 -0
  122. data/spec/rr/wildcard_matchers/range_spec.rb +35 -0
  123. data/spec/rr/wildcard_matchers/regexp_spec.rb +43 -0
  124. data/spec/rr_spec.rb +28 -0
  125. data/spec/rspec_spec_suite.rb +16 -0
  126. data/spec/spec_helper.rb +107 -0
  127. data/spec/spec_suite.rb +27 -0
  128. data/spec/spy_verification_spec.rb +129 -0
  129. data/spec/test_unit_spec_suite.rb +21 -0
  130. metadata +187 -0
data/CHANGES ADDED
@@ -0,0 +1,196 @@
1
+ * 0.7.1
2
+ - Performance improvements
3
+
4
+ * 0.7.0
5
+ - Added spies (Patchs by Joe Ferris, Michael Niessner & Mike Mangino)
6
+ - Added strongly typed reimplementation doubles (Patch by Michael Niessner)
7
+
8
+ * 0.6.2
9
+ - Fixed DoubleDefinition chaining edge cases
10
+
11
+ * 0.6.1
12
+ - DoubleDefinitionCreatorProxy definition eval block is instance_evaled when the arity is not 1. When the arity is 1, the block is yielded with the DoubleDefinitionCreatorProxy passed in.
13
+
14
+ * 0.6.0
15
+ - Friendlier DoubleNotFound error message
16
+ - Implemented Double strategy creation methods (#mock, #stub, #proxy, #instance_of, and ! equivalents) on DoubleDefinition
17
+ - Implemented hash_including matcher (Patch by Matthew O'Conner)
18
+ - Implemented satisfy matcher (Patch by Matthew O'Conner)
19
+ - Implemented DoubleDefinitionCreator#mock!, #stub!, and #dont_allow!
20
+ - Modified api to method chain Doubles
21
+ - Fix conflict with Mocha overriding Object#verify
22
+
23
+ * 0.5.0
24
+ - Method chaining Doubles (Patch by Nick Kallen)
25
+ - Chained ordered expectations (Patch by Nick Kallen)
26
+ - Space#verify_doubles can take one or more objects with DoubleInjections to be verified
27
+
28
+ * 0.4.10
29
+ - DoubleDefinitionCreatorProxy does not undef #object_id
30
+ - Fixed rdoc pointer to README
31
+
32
+ * 0.4.9
33
+ - Proxying from RR module to RR::Space.instance
34
+
35
+ * 0.4.8
36
+ - Fixed issue with Hash arguments
37
+
38
+ * 0.4.7
39
+ - Improved error message
40
+
41
+ * 0.4.6
42
+ - Added Double#verbose and Double#verbose?
43
+
44
+ * 0.4.5
45
+ - Fixed doubles for == and #eql? methods
46
+
47
+ * 0.4.4
48
+ - Doc improvements
49
+ - Methods that are not alphabetic, such as ==, can be doubles
50
+
51
+ * 0.4.3
52
+ - Doc improvements
53
+ - Cleanup
54
+ - Finished renaming scenario to double
55
+
56
+ * 0.4.2
57
+ - Renamed DoubleInsertion to DoubleInjection to be consistent with Mocha terminology
58
+
59
+ * 0.4.1
60
+ - Fixed backward compatability issues with rspec
61
+ - Renamed Space#verify_double_insertions to #verify_doubles
62
+
63
+ * 0.4.0
64
+ - Documentation improvements
65
+ - Renamed Double to DoubleInsertion
66
+ - Renamed Scenario to Double
67
+
68
+ * 0.3.11
69
+ - Fixed [#13724] Mock Proxy on Active Record Association proxies causes error
70
+
71
+ * 0.3.10
72
+ - Fixed [#13139] Blocks added to proxy sets the return_value and not the after_call callback
73
+
74
+ * 0.3.9
75
+ - Alias probe to proxy
76
+
77
+ * 0.3.8
78
+ - Implemented [#13009] Better error mesage from TimesCalledMatcher
79
+
80
+ * 0.3.7
81
+ - Fixed [#12928] Reset doubles fails on Rails association proxies
82
+
83
+ * 0.3.6
84
+ - Fixed [#12765] Issues with ObjectSpace._id2ref
85
+
86
+ * 0.3.5
87
+ - trim_backtrace is only set for Test::Unit
88
+
89
+ * 0.3.4
90
+ - Implemented instance_of
91
+
92
+ * 0.3.3
93
+ - Fixed [#12495] Error Probing method_missing interaction
94
+
95
+ * 0.3.2
96
+ - Fixed [#12486] ScenarioMethodProxy when Kernel passed into instance methods
97
+
98
+ * 0.3.1
99
+ - Automatically require Test::Unit and Rspec adapters
100
+
101
+ * 0.3.0
102
+ - ScenarioCreator strategy method chaining
103
+ - Removed mock_probe
104
+ - Removed stub_probe
105
+
106
+ * 0.2.5
107
+ - mock takes method_name argument
108
+ - stub takes method_name argument
109
+ - mock_probe takes method_name argument
110
+ - stub_probe takes method_name argument
111
+ - probe takes method_name argument
112
+ - dont_allow takes method_name argument
113
+ - do_not_allow takes method_name argument
114
+
115
+ * 0.2.4
116
+ - Space#doubles key is now the object id
117
+ - Fixed [#12402] Stubbing return value of probes fails after calling the stubbed method two times
118
+
119
+ * 0.2.3
120
+ - Added RRMethods#rr_verify and RRMethods#rr_reset
121
+
122
+ * 0.2.2
123
+ - Fixed "singleton method bound for a different object"
124
+ - Doing Method aliasing again to store original method
125
+
126
+ * 0.2.1
127
+ - Added mock_probe
128
+ - Added stub_probe
129
+ - Probe returns the return value of the passed in block, instead of ignoring its return value
130
+ - Scenario#after_call returns the return value of the passed in block
131
+ - Not using method aliasing to store original method
132
+ - Renamed DoubleMethods to RRMethods
133
+ - Added RRMethods#mock_probe
134
+
135
+ * 0.1.15
136
+ - Fixed [#12333] Rebinding original_methods causes blocks not to work
137
+
138
+ * 0.1.14
139
+ - Introduced concept of Terminal and NonTerminal TimesCalledMatchers
140
+ - Doubles that can be called many times can be replaced
141
+ - Terminal Scenarios are called before NonTerminal Scenarios
142
+ - Error message tweaking
143
+ - Raise error when making a Scenarios with NonTerminal TimesMatcher Ordered
144
+
145
+ * 0.1.13
146
+ - Fixed [#12290] Scenario#returns with false causes a return value of nil
147
+
148
+ * 0.1.12
149
+ - Fixed bug where Creators methods are not removed when methods are defined on Object
150
+ - Fixed [#12289] Creators methods are not removed in Rails environment
151
+
152
+ * 0.1.11
153
+ - Fixed [#12287] AtLeastMatcher does not cause Scenario to be called
154
+
155
+ * 0.1.10
156
+ - Fixed [#12286] AnyArgumentExpectation#expected_arguments not implemented
157
+
158
+ * 0.1.9
159
+ - Added DoubleMethods#any_times
160
+ - Added Scenario#any_number_of_times
161
+
162
+ * 0.1.8
163
+ - TimesCalledError Message Formatted to be on multiple lines
164
+ - ScenarioNotFoundError Message includes all Scenarios for the Double
165
+ - ScenarioOrderError shows list of remaining ordered scenarios
166
+
167
+ * 0.1.7
168
+ - Fixed [#12194] Double#reset_doubles are not clearing Ordered Scenarios bug
169
+ - Added Space#reset
170
+ - Space#reset_doubles and Space#reset_ordered_scenarios is now protected
171
+ - Added Scenario#at_least
172
+ - Added Scenario#at_most
173
+
174
+ * 0.1.6
175
+ - [#12120] probe allows a the return value to be intercepted
176
+
177
+ * 0.1.5
178
+ - TimesCalledExpectation says how many times were called and how many times called were expected on error
179
+
180
+ * 0.1.4
181
+ - TimesCalledError prints the backtrace to where the Scenario was defined when being verified
182
+ - Error message includes method name when Scenario is not found
183
+
184
+ * 0.1.3
185
+ - Fixed issue where Double#placeholder_name issues when Double method name has a ! or ?
186
+
187
+ * 0.1.2
188
+ - Scenario#returns also accepts an argument
189
+ - Implemented Scenario#yields
190
+
191
+ * 0.1.1
192
+ - Trim the backtrace for Rspec and Test::Unit
193
+ - Rspec and Test::Unit integration fixes
194
+
195
+ * 0.1.0
196
+ - Initial Release
data/README.rdoc ADDED
@@ -0,0 +1,329 @@
1
+ = RR
2
+
3
+ RR (Double Ruby) is a test double framework that features a rich
4
+ selection of double techniques and a terse syntax.
5
+
6
+ == More Information
7
+ === Mailing Lists
8
+ * double-ruby-users@rubyforge.org
9
+ * double-ruby-devel@rubyforge.org
10
+
11
+ === Websites
12
+ * http://rubyforge.org/projects/double-ruby
13
+ * http://github.com/btakita/rr
14
+
15
+ == What is a Test Double?
16
+ A Test Double is a generalization of something that replaces a real
17
+ object to make it easier to test another object. Its like a stunt
18
+ double for tests. The following are test doubles:
19
+ * Mocks
20
+ * Stubs
21
+ * Fakes
22
+ * Spies
23
+ * Proxies
24
+ http://xunitpatterns.com/Test%20Double.html
25
+
26
+ Currently RR implements mocks, stubs, proxies, and spies. Fakes usually require custom code, so it is beyond the scope of RR.
27
+
28
+ == Using RR
29
+ === test/unit
30
+ class Test::Unit::TestCase
31
+ include RR::Adapters::TestUnit
32
+ end
33
+
34
+ === rspec
35
+ Spec::Runners.configure do |config|
36
+ config.mock_with :rr
37
+ # or if that doesn't work due to a version incompatibility
38
+ # config.mock_with RR::Adapters::Rspec
39
+ end
40
+
41
+ == Syntax between RR and other double/mock frameworks
42
+ === Terse Syntax
43
+ One of the goals of RR is to make doubles more scannable.
44
+ This is accomplished by making the double declaration look as much as the actual method invocation as possible.
45
+ Here is RR compared to other mock frameworks:
46
+
47
+ flexmock(User).should_receive(:find).with('42').and_return(jane) # Flexmock
48
+ User.should_receive(:find).with('42').and_return(jane) # Rspec
49
+ User.expects(:find).with('42').returns {jane} # Mocha
50
+ User.should_receive(:find).with('42') {jane} # Rspec using return value blocks
51
+ mock(User).find('42') {jane} # RR
52
+
53
+ === Double Injections (a.k.a Partial Mocking)
54
+ RR utilizes a technique known as "double injection".
55
+
56
+ my_object = MyClass.new
57
+ mock(my_object).hello
58
+
59
+ Compare this with doing a mock in mocha:
60
+ my_mocked_object = mock()
61
+ my_mocked_object.expects(:hello)
62
+
63
+ == Pure Mock objects
64
+ If you wish to use objects for the sole purpose of being a mock, you can
65
+ do so by creating an empty object.
66
+ mock(my_mock_object = Object.new).hello
67
+
68
+ or by using mock!
69
+ my_mock_object = mock!.hello.subject # Mocks the #hello method and retrieves that object via the #subject method
70
+
71
+ === No should_receive or expects method
72
+ RR uses method_missing to set your method expectation. This means you do not
73
+ need to use a method such as should_receive or expects.
74
+
75
+ mock(my_object).hello # The hello method on my_object is mocked
76
+
77
+ Mocha:
78
+ my_object.expects(:hello) # expects sets the hello method expectation
79
+ Rspec mocks:
80
+ my_object.should_receive(:hello) # should_receive sets the hello method expectation
81
+
82
+ === with method call is not necessary
83
+ Since RR uses method_missing, it also makes using the #with method unnecessary in most circumstances
84
+ to set the argument expectations.
85
+
86
+ mock(my_object).hello('bob', 'jane')
87
+
88
+ Mocha:
89
+ my_object.expects(:hello).with('bob', 'jane')
90
+ Rspec mocks:
91
+ my_object.should_receive(:hello).with('bob', 'jane')
92
+
93
+ === using a block to set the return value
94
+ RR supports using a block to set the return value. RR also has the #returns method.
95
+ Both of the examples are equivalent.
96
+
97
+ mock(my_object).hello('bob', 'jane') {'Hello Bob and Jane'}
98
+ mock(my_object).hello('bob', 'jane').returns('Hello Bob and Jane')
99
+
100
+ Mocha:
101
+ my_object.expects(:hello).with('bob', 'jane').returns('Hello Bob and Jane')
102
+ Rspec mocks:
103
+ my_object.should_receive(:hello).with('bob', 'jane').and_return('Hello Bob and Jane')
104
+ my_object.should_receive(:hello).with('bob', 'jane') {'Hello Bob and Jane'} #rspec also supports blocks for the return value
105
+
106
+ == Using RR
107
+ To create a double on an object, you can use the following methods:
108
+ * mock or mock!
109
+ * stub or stub!
110
+ * dont_allow or dont_allow!
111
+ * proxy or proxy!
112
+ * instance_of or instance_of!
113
+
114
+ These methods are composable. mock, stub, and dont_allow can be used by themselves and
115
+ are mutually exclusive.
116
+ proxy and instance_of must be chained with mock or stub. You can also chain
117
+ proxy and instance_of together.
118
+
119
+ The ! (bang) version of these methods causes the subject object of the Double to be instantiated.
120
+
121
+ === mock
122
+ mock replaces the method on the object with an expectation and implementation.
123
+ The expectations are a mock will be called with certain arguments a certain
124
+ number of times (the default is once). You can also set the return value
125
+ of the method invocation.
126
+
127
+ See http://xunitpatterns.com/Mock%20Object.html
128
+
129
+ The following example sets an expectation that the view will receive a method
130
+ call to #render with the arguments {:partial => "user_info"} once.
131
+ When the method is called "Information" is returned.
132
+ view = controller.template
133
+ mock(view).render(:partial => "user_info") {"Information"}
134
+
135
+ === stub
136
+ stub replaces the method on the object with only an implementation. You
137
+ can still use arguments to differentiate which stub gets invoked.
138
+
139
+ See http://xunitpatterns.com/Test%20Stub.html
140
+
141
+ The following example makes the User.find method return jane when passed
142
+ '42' and returns bob when passed '99'. If another id is passed to User.find,
143
+ an exception is raised.
144
+ jane = User.new
145
+ bob = User.new
146
+ stub(User).find('42') {jane}
147
+ stub(User).find('99') {bob}
148
+ stub(User).find do |id|
149
+ raise "Unexpected id #{id.inspect} passed to me"
150
+ end
151
+
152
+ === dont_allow - aliased with do_not_allow, dont_call, and do_not_call
153
+ dont_allow sets an expectation on the Double that it will never be called.
154
+ If the Double is called, then a TimesCalledError is raised.
155
+ dont_allow(User).find('42')
156
+ User.find('42') # raises a TimesCalledError
157
+
158
+ === mock.proxy
159
+ mock.proxy replaces the method on the object with an expectation, implementation, and
160
+ also invokes the actual method. mock.proxy also intercepts the return value and
161
+ passes it into the return value block.
162
+
163
+ The following example makes sets an expectation that view.render({:partial => "right_navigation"})
164
+ gets called once and return the actual content of the rendered partial template.
165
+ A call to view.render({:partial => "user_info"}) will render the user_info
166
+ partial template and send the content into the block and is represented by the html variable.
167
+ An assertion is done on the html and "Different html" is returned.
168
+ view = controller.template
169
+ mock.proxy(view).render(:partial => "right_navigation")
170
+ mock.proxy(view).render(:partial => "user_info") do |html|
171
+ html.should include("John Doe")
172
+ "Different html"
173
+ end
174
+
175
+ You can also use mock.proxy to set expectations on the returned value. In
176
+ the following example, a call to User.find('5') does the normal ActiveRecord
177
+ implementation and passes the actual value, represented by the variable bob,
178
+ into the block. bob is then set with a mock.proxy for projects to return
179
+ only the first 3 projects. bob is also mocked with valid? to return false.
180
+ mock.proxy(User).find('5') do |bob|
181
+ mock.proxy(bob).projects do |projects|
182
+ projects[0..3]
183
+ end
184
+ mock(bob).valid? {false}
185
+ bob
186
+ end
187
+
188
+ === stub.proxy
189
+ Intercept the return value of a method call.
190
+ The following example verifies render partial will be called and
191
+ renders the partial.
192
+
193
+ view = controller.template
194
+ stub.proxy(view).render(:partial => "user_info") do |html|
195
+ html.should include("Joe Smith")
196
+ html
197
+ end
198
+
199
+ === instance_of
200
+ Put double scenarios on instances of a Class.
201
+
202
+ mock.instance_of(User).valid? {false}
203
+
204
+ === Spies
205
+
206
+ Adding a DoubleInjection to an Object + Method (done by stub, mock, or dont_allow) causes RR to record any method
207
+ invocations to the Object + method. Assertions can then be made on the recorded method calls.
208
+
209
+ ==== test/unit
210
+
211
+ subject = Object.new
212
+ stub(subject).foo
213
+ subject.foo(1)
214
+ assert_received(subject) {|subject| subject.foo(1)}
215
+ assert_received(subject) {|subject| subject.bar} # This fails
216
+
217
+ ==== rspec
218
+
219
+ subject = Object.new
220
+ stub(subject).foo
221
+ subject.foo(1)
222
+ subject.should have_received.foo(1)
223
+ subject.should have_received.bar # this fails
224
+
225
+ === Block Syntax
226
+ The block syntax has two modes
227
+ * A normal block mode with a DoubleDefinitionCreatorProxy argument
228
+
229
+ script = MyScript.new
230
+ mock(script) do |expect|
231
+ expect.system("cd #{RAILS_ENV}") {true}
232
+ expect.system("rake foo:bar") {true}
233
+ expect.system("rake baz") {true}
234
+ end
235
+
236
+ * An instance_eval mode where the DoubleDefinitionCreatorProxy is instance_evaled
237
+
238
+ script = MyScript.new
239
+ mock(script) do
240
+ system("cd #{RAILS_ENV}") {true}
241
+ system("rake foo:bar") {true}
242
+ system("rake baz") {true}
243
+ end
244
+
245
+ === Block Syntax with explicit DoubleDefinitionCreatorProxy argument
246
+
247
+
248
+ === Double Graphs
249
+ RR has a method-chaining api support for Double graphs. For example,
250
+ lets say you want an object to receive a method call to #foo, and have
251
+ the return value receive a method call to #bar.
252
+
253
+ In RR, you would do:
254
+ stub(object).foo.stub!.bar {:baz}
255
+ object.foo.bar # :baz
256
+ # or
257
+ stub(object).foo {stub!.bar {:baz}}
258
+ object.foo.bar # :baz
259
+ # or
260
+ bar = stub!.bar {:baz}
261
+ stub(object).foo {bar}
262
+ object.foo.bar # :baz
263
+
264
+ === Argument Wildcard matchers
265
+ ==== anything
266
+ mock(object).foobar(1, anything)
267
+ object.foobar(1, :my_symbol)
268
+
269
+ ==== is_a
270
+ mock(object).foobar(is_a(Time))
271
+ object.foobar(Time.now)
272
+
273
+ ==== numeric
274
+ mock(object).foobar(numeric)
275
+ object.foobar(99)
276
+
277
+ ==== boolean
278
+ mock(object).foobar(boolean)
279
+ object.foobar(false)
280
+
281
+ ==== duck_type
282
+ mock(object).foobar(duck_type(:walk, :talk))
283
+ arg = Object.new
284
+ def arg.walk; 'waddle'; end
285
+ def arg.talk; 'quack'; end
286
+ object.foobar(arg)
287
+
288
+ ==== Ranges
289
+ mock(object).foobar(1..10)
290
+ object.foobar(5)
291
+
292
+ ==== Regexps
293
+ mock(object).foobar(/on/)
294
+ object.foobar("ruby on rails")
295
+
296
+ ==== hash_including
297
+ mock(object).foobar(hash_including(:red => "#FF0000", :blue => "#0000FF"))
298
+ object.foobar({:red => "#FF0000", :blue => "#0000FF", :green => "#00FF00"})
299
+
300
+ ==== satisfy
301
+ mock(object).foobar(satisfy {|arg| arg.length == 2})
302
+ object.foobar("xy")
303
+
304
+ === Invocation Amount Wildcard Matchers
305
+ ==== any_times
306
+ mock(object).method_name(anything).times(any_times) {return_value}
307
+
308
+ == Special Thanks To
309
+ With any development effort, there are countless people who have contributed
310
+ to making it possible. We all are standing on the shoulders of giants.
311
+ * Aslak Hellesoy for Developing Rspec
312
+ * Dan North for syntax ideas
313
+ * Dave Astels for some BDD inspiration
314
+ * David Chelimsky for encouragement to make the RR framework, for developing the Rspec mock framework, and syntax ideas
315
+ * Daniel Sudol for identifing performance issues with RR
316
+ * Felix Morio for pairing with me
317
+ * Gerard Meszaros for his excellent book "xUnit Test Patterns"
318
+ * James Mead for developing Mocha
319
+ * Jeff Whitmire for documentation suggestions
320
+ * Jim Weirich for developing Flexmock, the first Terse ruby mock framework in Ruby
321
+ * Joe Ferris for patches
322
+ * Matthew O'Conner for patches
323
+ * Michael Niessner for patches and pairing with me
324
+ * Mike Mangino (from Elevated Rails) for patches and pairing with me
325
+ * Nick Kallen for documentation suggestions, bug reports, and patches
326
+ * Nathan Sobo for various ideas and inspiration for cleaner and more expressive code
327
+ * Parker Thompson for pairing with me
328
+ * Pivotal Labs for sponsoring RR development
329
+ * Stephen Baker for Developing Rspec