rspec 0.7.5.1 → 0.8.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 (194) hide show
  1. data/CHANGES +60 -1
  2. data/EXAMPLES.rd +38 -19
  3. data/MIT-LICENSE +1 -1
  4. data/README +24 -17
  5. data/RELEASE-PLAN +117 -0
  6. data/Rakefile +24 -18
  7. data/TODO.0.8.0 +5 -0
  8. data/examples/auto_spec_name_generation_example.rb +18 -0
  9. data/examples/custom_expectation_matchers.rb +53 -0
  10. data/examples/dynamic_spec.rb +9 -0
  11. data/examples/io_processor_spec.rb +2 -2
  12. data/examples/mocking_example.rb +4 -4
  13. data/examples/partial_mock_example.rb +2 -2
  14. data/examples/predicate_example.rb +2 -2
  15. data/examples/stack_spec.rb +32 -36
  16. data/examples/stubbing_example.rb +19 -19
  17. data/examples/test_case_spec.rb +6 -6
  18. data/lib/spec.rb +3 -0
  19. data/lib/spec/callback.rb +8 -0
  20. data/lib/spec/callback/extensions/object.rb +4 -0
  21. data/lib/spec/deprecated.rb +3 -0
  22. data/lib/spec/expectations.rb +44 -17
  23. data/lib/spec/expectations/extensions.rb +1 -2
  24. data/lib/spec/expectations/extensions/object.rb +78 -130
  25. data/lib/spec/expectations/extensions/string_and_symbol.rb +17 -0
  26. data/lib/spec/expectations/handler.rb +47 -0
  27. data/lib/spec/expectations/should/base.rb +32 -29
  28. data/lib/spec/expectations/should/change.rb +1 -1
  29. data/lib/spec/expectations/should/have.rb +9 -17
  30. data/lib/spec/expectations/should/not.rb +54 -56
  31. data/lib/spec/expectations/should/should.rb +59 -65
  32. data/lib/spec/expectations/sugar.rb +27 -4
  33. data/lib/spec/matchers.rb +160 -0
  34. data/lib/spec/matchers/be.rb +161 -0
  35. data/lib/spec/matchers/be_close.rb +37 -0
  36. data/lib/spec/matchers/change.rb +120 -0
  37. data/lib/spec/matchers/eql.rb +43 -0
  38. data/lib/spec/matchers/equal.rb +43 -0
  39. data/lib/spec/matchers/has.rb +44 -0
  40. data/lib/spec/matchers/have.rb +140 -0
  41. data/lib/spec/matchers/include.rb +50 -0
  42. data/lib/spec/matchers/match.rb +41 -0
  43. data/lib/spec/matchers/raise_error.rb +100 -0
  44. data/lib/spec/matchers/respond_to.rb +35 -0
  45. data/lib/spec/matchers/satisfy.rb +47 -0
  46. data/lib/spec/matchers/throw_symbol.rb +75 -0
  47. data/lib/spec/mocks.rb +224 -1
  48. data/lib/spec/mocks/argument_expectation.rb +16 -2
  49. data/lib/spec/mocks/error_generator.rb +5 -3
  50. data/lib/spec/mocks/errors.rb +2 -2
  51. data/lib/spec/mocks/extensions/object.rb +1 -1
  52. data/lib/spec/mocks/message_expectation.rb +29 -19
  53. data/lib/spec/mocks/{mock_methods.rb → methods.rb} +5 -5
  54. data/lib/spec/mocks/mock.rb +2 -2
  55. data/lib/spec/mocks/mock_handler.rb +81 -68
  56. data/lib/spec/rake/spectask.rb +7 -12
  57. data/lib/spec/rake/verify_rcov.rb +1 -1
  58. data/lib/spec/runner.rb +117 -0
  59. data/lib/spec/runner/command_line.rb +8 -5
  60. data/lib/spec/runner/context.rb +13 -37
  61. data/lib/spec/runner/context_eval.rb +4 -3
  62. data/lib/spec/runner/context_runner.rb +7 -4
  63. data/lib/spec/runner/drb_command_line.rb +1 -1
  64. data/lib/spec/runner/execution_context.rb +3 -11
  65. data/lib/spec/runner/extensions/kernel.rb +7 -5
  66. data/lib/spec/runner/extensions/object.rb +4 -1
  67. data/lib/spec/runner/formatter/base_text_formatter.rb +11 -3
  68. data/lib/spec/runner/formatter/html_formatter.rb +21 -10
  69. data/lib/spec/runner/heckle_runner.rb +24 -8
  70. data/lib/spec/runner/heckle_runner_win.rb +10 -0
  71. data/lib/spec/runner/option_parser.rb +58 -13
  72. data/lib/spec/runner/spec_matcher.rb +22 -29
  73. data/lib/spec/runner/spec_parser.rb +1 -0
  74. data/lib/spec/runner/specification.rb +36 -22
  75. data/lib/spec/translator.rb +87 -0
  76. data/lib/spec/version.rb +16 -7
  77. data/spec/spec/callback/callback_container_spec.rb +27 -0
  78. data/spec/spec/callback/module_spec.rb +37 -0
  79. data/spec/spec/callback/object_spec.rb +90 -0
  80. data/spec/spec/callback/object_with_class_callback_spec.rb +19 -0
  81. data/spec/spec/expectations/differs/default_spec.rb +107 -0
  82. data/spec/spec/expectations/extensions/object_spec.rb +46 -0
  83. data/spec/spec/expectations/fail_with_spec.rb +71 -0
  84. data/spec/spec/expectations/should/should_==_spec.rb +19 -0
  85. data/spec/spec/expectations/should/should_=~_spec.rb +13 -0
  86. data/spec/spec/expectations/should/should_be_a_kind_of_spec.rb +21 -0
  87. data/spec/spec/expectations/should/should_be_an_instance_of_spec.rb +30 -0
  88. data/spec/spec/expectations/should/should_be_arbitrary_predicate_spec.rb +81 -0
  89. data/spec/spec/expectations/should/should_be_close_spec.rb +18 -0
  90. data/spec/spec/expectations/should/should_be_comparison_operator_spec.rb +44 -0
  91. data/spec/spec/expectations/should/should_be_false_spec.rb +39 -0
  92. data/spec/spec/expectations/should/should_be_spec.rb +11 -0
  93. data/spec/spec/expectations/should/should_be_true_spec.rb +27 -0
  94. data/spec/spec/expectations/should/should_change_spec.rb +184 -0
  95. data/spec/spec/expectations/should/should_eql_spec.rb +11 -0
  96. data/spec/spec/expectations/should/should_equal_spec.rb +11 -0
  97. data/spec/spec/expectations/should/should_have_at_least_spec.rb +53 -0
  98. data/spec/spec/expectations/should/should_have_at_most_spec.rb +45 -0
  99. data/spec/spec/expectations/should/should_have_key_spec.rb +21 -0
  100. data/spec/spec/expectations/should/should_have_spec.rb +64 -0
  101. data/spec/spec/expectations/should/should_include_spec.rb +59 -0
  102. data/spec/spec/expectations/should/should_match_spec.rb +25 -0
  103. data/spec/spec/expectations/should/should_not_==_spec.rb +15 -0
  104. data/spec/spec/expectations/should/should_not_be_a_kind_of_spec.rb +21 -0
  105. data/spec/spec/expectations/should/should_not_be_an_instance_of_spec.rb +11 -0
  106. data/spec/spec/expectations/should/should_not_be_arbitrary_predicate_spec.rb +68 -0
  107. data/spec/spec/expectations/should/should_not_be_spec.rb +11 -0
  108. data/spec/spec/expectations/should/should_not_change_spec.rb +24 -0
  109. data/spec/spec/expectations/should/should_not_eql_spec.rb +11 -0
  110. data/spec/spec/expectations/should/should_not_equal_spec.rb +11 -0
  111. data/spec/spec/expectations/should/should_not_have_key_spec.rb +15 -0
  112. data/spec/spec/expectations/should/should_not_include_spec.rb +58 -0
  113. data/spec/spec/expectations/should/should_not_match_spec.rb +11 -0
  114. data/spec/spec/expectations/should/should_not_raise_spec.rb +75 -0
  115. data/spec/spec/expectations/should/should_not_respond_to_spec.rb +15 -0
  116. data/spec/spec/expectations/should/should_not_throw_spec.rb +35 -0
  117. data/spec/spec/expectations/should/should_raise_spec.rb +66 -0
  118. data/spec/spec/expectations/should/should_respond_to_spec.rb +15 -0
  119. data/spec/spec/expectations/should/should_satisfy_spec.rb +35 -0
  120. data/spec/spec/expectations/should/should_throw_spec.rb +27 -0
  121. data/spec/spec/matchers/be_close_spec.rb +33 -0
  122. data/spec/spec/matchers/be_spec.rb +182 -0
  123. data/spec/spec/matchers/change_spec.rb +232 -0
  124. data/spec/spec/matchers/description_generation_spec.rb +147 -0
  125. data/spec/spec/matchers/eql_spec.rb +41 -0
  126. data/spec/spec/matchers/equal_spec.rb +41 -0
  127. data/spec/spec/matchers/handler_spec.rb +75 -0
  128. data/spec/spec/matchers/has_spec.rb +37 -0
  129. data/spec/spec/matchers/have_spec.rb +259 -0
  130. data/spec/spec/matchers/include_spec.rb +33 -0
  131. data/spec/spec/matchers/match_spec.rb +37 -0
  132. data/spec/spec/matchers/matcher_methods_spec.rb +85 -0
  133. data/spec/spec/matchers/raise_error_spec.rb +147 -0
  134. data/spec/spec/matchers/respond_to_spec.rb +30 -0
  135. data/spec/spec/matchers/satisfy_spec.rb +36 -0
  136. data/spec/spec/matchers/throw_symbol_spec.rb +59 -0
  137. data/spec/spec/mocks/any_number_of_times_spec.rb +34 -0
  138. data/spec/spec/mocks/at_least_spec.rb +97 -0
  139. data/spec/spec/mocks/at_most_spec.rb +97 -0
  140. data/spec/spec/mocks/bug_report_7611_spec.rb +19 -0
  141. data/spec/spec/mocks/bug_report_7805_spec.rb +22 -0
  142. data/spec/spec/mocks/bug_report_8165_spec.rb +31 -0
  143. data/spec/spec/mocks/bug_report_8302_spec.rb +26 -0
  144. data/spec/spec/mocks/failing_mock_argument_constraints_spec.rb +74 -0
  145. data/spec/spec/mocks/mock_ordering_spec.rb +80 -0
  146. data/spec/spec/mocks/mock_spec.rb +407 -0
  147. data/spec/spec/mocks/multiple_return_value_spec.rb +113 -0
  148. data/spec/spec/mocks/null_object_mock_spec.rb +40 -0
  149. data/spec/spec/mocks/once_counts_spec.rb +56 -0
  150. data/spec/spec/mocks/options_hash_spec.rb +31 -0
  151. data/spec/spec/mocks/partial_mock_spec.rb +52 -0
  152. data/spec/spec/mocks/partial_mock_using_mocks_directly_spec.rb +64 -0
  153. data/spec/spec/mocks/passing_mock_argument_constraints_spec.rb +92 -0
  154. data/spec/spec/mocks/precise_counts_spec.rb +56 -0
  155. data/spec/spec/mocks/record_messages_spec.rb +26 -0
  156. data/spec/spec/mocks/stub_spec.rb +159 -0
  157. data/spec/spec/mocks/twice_counts_spec.rb +67 -0
  158. data/spec/spec/runner/command_line_spec.rb +32 -0
  159. data/spec/spec/runner/context_matching_spec.rb +28 -0
  160. data/spec/spec/runner/context_runner_spec.rb +100 -0
  161. data/spec/spec/runner/context_spec.rb +405 -0
  162. data/spec/spec/runner/drb_command_line_spec.rb +74 -0
  163. data/spec/spec/runner/execution_context_spec.rb +52 -0
  164. data/spec/spec/runner/formatter/html_formatter_spec.rb +40 -0
  165. data/spec/spec/runner/formatter/progress_bar_formatter_dry_run_spec.rb +21 -0
  166. data/spec/spec/runner/formatter/progress_bar_formatter_failure_dump_spec.rb +36 -0
  167. data/spec/spec/runner/formatter/progress_bar_formatter_spec.rb +78 -0
  168. data/spec/spec/runner/formatter/rdoc_formatter_dry_run_spec.rb +18 -0
  169. data/spec/spec/runner/formatter/rdoc_formatter_spec.rb +41 -0
  170. data/spec/spec/runner/formatter/specdoc_formatter_dry_run_spec.rb +21 -0
  171. data/spec/spec/runner/formatter/specdoc_formatter_spec.rb +46 -0
  172. data/spec/spec/runner/heckle_runner_spec.rb +63 -0
  173. data/spec/spec/runner/heckler_spec.rb +14 -0
  174. data/spec/spec/runner/kernel_ext_spec.rb +16 -0
  175. data/spec/spec/runner/noisy_backtrace_tweaker_spec.rb +45 -0
  176. data/spec/spec/runner/object_ext_spec.rb +11 -0
  177. data/spec/spec/runner/option_parser_spec.rb +269 -0
  178. data/spec/spec/runner/quiet_backtrace_tweaker_spec.rb +47 -0
  179. data/spec/spec/runner/reporter_spec.rb +126 -0
  180. data/spec/spec/runner/spec_matcher_spec.rb +107 -0
  181. data/spec/spec/runner/spec_name_generation_spec.rb +102 -0
  182. data/spec/spec/runner/spec_parser_spec.rb +37 -0
  183. data/spec/spec/runner/specification_class_spec.rb +72 -0
  184. data/spec/spec/runner/specification_instance_spec.rb +160 -0
  185. data/spec/spec/runner/specification_should_raise_spec.rb +136 -0
  186. data/spec/spec/spec_classes.rb +102 -0
  187. data/spec/spec/translator_spec.rb +79 -0
  188. data/spec/spec_helper.rb +35 -0
  189. metadata +141 -9
  190. data/bin/drbspec +0 -3
  191. data/lib/spec/expectations/diff.rb +0 -28
  192. data/lib/spec/expectations/extensions/numeric.rb +0 -19
  193. data/lib/spec/expectations/extensions/string.rb +0 -22
  194. data/lib/spec/expectations/message_builder.rb +0 -13
@@ -1,4 +1,4 @@
1
- require 'spec/mocks/mock_methods'
1
+ require 'spec/mocks/methods'
2
2
  require 'spec/mocks/mock_handler'
3
3
  require 'spec/mocks/mock'
4
4
  require 'spec/mocks/argument_expectation'
@@ -7,3 +7,226 @@ require 'spec/mocks/order_group'
7
7
  require 'spec/mocks/errors'
8
8
  require 'spec/mocks/error_generator'
9
9
  require 'spec/mocks/extensions/object'
10
+
11
+ module Spec
12
+ # == Mocks and Stubs
13
+ #
14
+ # RSpec will create Mock Objects and Stubs for you at runtime, or attach stub/mock behaviour
15
+ # to any of your real objects (Partial Mock/Stub). Because the underlying implementation
16
+ # for mocks and stubs is the same, you can intermingle mock and stub
17
+ # behaviour in either dynamically generated mocks or your pre-existing classes.
18
+ # There is a semantic difference in how they are created, however,
19
+ # which can help clarify the role it is playing within a given spec.
20
+ #
21
+ # == Mock Objects
22
+ #
23
+ # Mocks are objects that allow you to set and verify expectations that they will
24
+ # receive specific messages during run time. They are very useful for specifying how the subject of
25
+ # the spec interacts with its collaborators. This approach is widely known as "interaction
26
+ # testing".
27
+ #
28
+ # Mocks are also very powerful as a design tool. As you are
29
+ # driving the implementation of a given class, Mocks provide an anonymous
30
+ # collaborator that can change in behaviour as quickly as you can write an expectation in your
31
+ # spec. This flexibility allows you to design the interface of a collaborator that often
32
+ # does not yet exist. As the shape of the class being specified becomes more clear, so do the
33
+ # requirements for its collaborators - often leading to the discovery of new types that are
34
+ # needed in your system.
35
+ #
36
+ # Read Endo-Testing[http://www.mockobjects.com/files/endotesting.pdf] for a much
37
+ # more in depth description of this process.
38
+ #
39
+ # == Stubs
40
+ #
41
+ # Stubs are objects that allow you to set "stub" responses to
42
+ # messages. As Martin Fowler points out on his site,
43
+ # mocks_arent_stubs[http://www.martinfowler.com/articles/mocksArentStubs.html].
44
+ # Paraphrasing Fowler's paraphrasing
45
+ # of Gerard Meszaros: Stubs provide canned responses to messages they might receive in a test, while
46
+ # mocks allow you to specify and, subsquently, verify that certain messages should be received during
47
+ # the execution of a test.
48
+ #
49
+ # == Partial Mocks/Stubs
50
+ #
51
+ # RSpec also supports partial mocking/stubbing, allowing you to add stub/mock behaviour
52
+ # to instances of your existing classes. This is generally
53
+ # something to be avoided, because changes to the class can have ripple effects on
54
+ # seemingly unrelated specs. When specs fail due to these ripple effects, the fact
55
+ # that some methods are being mocked can make it difficult to understand why a
56
+ # failure is occurring.
57
+ #
58
+ # That said, partials do allow you to expect and
59
+ # verify interactions with class methods such as +#find+ and +#create+
60
+ # on Ruby on Rails model classes.
61
+ #
62
+ # == Further Reading
63
+ #
64
+ # There are many different viewpoints about the meaning of mocks and stubs. If you are interested
65
+ # in learning more, here is some recommended reading:
66
+ #
67
+ # * Mock Objects: http://www.mockobjects.com/
68
+ # * Endo-Testing: http://www.mockobjects.com/files/endotesting.pdf
69
+ # * Mock Roles, Not Objects: http://www.mockobjects.com/files/mockrolesnotobjects.pdf
70
+ # * Test Double Patterns: http://xunitpatterns.com/Test%20Double%20Patterns.html
71
+ # * Mocks aren't stubs: http://www.martinfowler.com/articles/mocksArentStubs.html
72
+ #
73
+ # == Creating a Mock
74
+ #
75
+ # You can create a mock in any specification (or setup) using:
76
+ #
77
+ # mock(name, options={})
78
+ #
79
+ # The optional +options+ argument is a +Hash+. Currently the only supported
80
+ # option is +:null_object+. Setting this to true instructs the mock to ignore
81
+ # any messages it hasn’t been told to expect – and quietly return itself. For example:
82
+ #
83
+ # mock("person", :null_object => true)
84
+ #
85
+ # == Creating a Stub
86
+ #
87
+ # You can create a stub in any specification (or setup) using:
88
+ #
89
+ # stub(name, stub_methods_and_values_hash)
90
+ #
91
+ # For example, if you wanted to create an object that always returns
92
+ # "More?!?!?!" to "please_sir_may_i_have_some_more" you would do this:
93
+ #
94
+ # stub("Mr Sykes", :please_sir_may_i_have_some_more => "More?!?!?!")
95
+ #
96
+ # == Creating a Partial Mock
97
+ #
98
+ # You don't really "create" a partial mock, you simply add method stubs and/or
99
+ # mock expectations to existing classes and objects:
100
+ #
101
+ # Factory.should_receive(:find).with(id).and_return(value)
102
+ # obj.stub!(:to_i).and_return(3)
103
+ # etc ...
104
+ #
105
+ # == Expecting Messages
106
+ #
107
+ # my_mock.should_receive(:sym)
108
+ # my_mock.should_not_receive(:sym)
109
+ #
110
+ # == Expecting Arguments
111
+ #
112
+ # my_mock.should_receive(:sym).with(*args)
113
+ # my_mock.should_not_receive(:sym).with(*args)
114
+ #
115
+ # == Argument Constraints using Expression Matchers
116
+ #
117
+ # Arguments that are passed to #with are compared with actual arguments received
118
+ # using == by default. In cases in which you want to specify things about the arguments
119
+ # rather than the arguments themselves, you can use any of the Expression Matchers.
120
+ # They don't all make syntactic sense (they were primarily designed for use with
121
+ # Spec::Expectations), but you are free to create your own custom Spec::Matchers.
122
+ #
123
+ # Spec::Mocks does provide one additional Matcher method named #ducktype.
124
+ #
125
+ # In addition, Spec::Mocks adds some keyword Symbols that you can use to
126
+ # specify certain kinds of arguments:
127
+ #
128
+ # my_mock.should_receive(:sym).with(:no_args)
129
+ # my_mock.should_receive(:sym).with(:any_args)
130
+ # my_mock.should_receive(:sym).with(1, :numeric, "b") #2nd argument can any type of Numeric
131
+ # my_mock.should_receive(:sym).with(1, :boolean, "b") #2nd argument can true or false
132
+ # my_mock.should_receive(:sym).with(1, :string, "b") #2nd argument can be any String
133
+ # my_mock.should_receive(:sym).with(1, /abc/, "b") #2nd argument can be any String matching the submitted Regexp
134
+ # my_mock.should_receive(:sym).with(1, :anything, "b") #2nd argument can be anything at all
135
+ # my_mock.should_receive(:sym).with(1, ducktype(:abs, :div), "b")
136
+ # #2nd argument can be object that responds to #abs and #div
137
+ #
138
+ # == Receive Counts
139
+ #
140
+ # my_mock.should_receive(:sym).once
141
+ # my_mock.should_receive(:sym).twice
142
+ # my_mock.should_receive(:sym).exactly(n).times
143
+ # my_mock.should_receive(:sym).at_least(:once)
144
+ # my_mock.should_receive(:sym).at_least(:twice)
145
+ # my_mock.should_receive(:sym).at_least(n).times
146
+ # my_mock.should_receive(:sym).at_most(:once)
147
+ # my_mock.should_receive(:sym).at_most(:twice)
148
+ # my_mock.should_receive(:sym).at_most(n).times
149
+ # my_mock.should_receive(:sym).any_number_of_times
150
+ #
151
+ # == Ordering
152
+ #
153
+ # my_mock.should_receive(:sym).ordered
154
+ # my_mock.should_receive(:other_sym).ordered
155
+ # #This will fail if the messages are received out of order
156
+ #
157
+ # == Setting Reponses
158
+ #
159
+ # Whether you are setting a mock expectation or a simple stub, you can tell the
160
+ # object precisely how to respond:
161
+ #
162
+ # my_mock.should_receive(:sym).and_return(value)
163
+ # my_mock.should_receive(:sym).exactly(3).times.and_return(value1, value2, value3)
164
+ # # returns value1 the first time, value2 the second, etc
165
+ # my_mock.should_receive(:sym).and_return { ... } #returns value returned by the block
166
+ # my_mock.should_receive(:sym).and_raise(error)
167
+ # #error can be an instantiated object or a class
168
+ # #if it is a class, it must be instantiable with no args
169
+ # my_mock.should_receive(:sym).and_throw(:sym)
170
+ # my_mock.should_receive(:sym).and_yield([array,of,values,to,yield])
171
+ #
172
+ # Any of these responses can be applied to a stub as well, but stubs do
173
+ # not support any qualifiers about the message received (i.e. you can't specify arguments
174
+ # or receive counts):
175
+ #
176
+ # my_mock.stub!(:sym).and_return(value)
177
+ # my_mock.stub!(:sym).and_return(value1, value2, value3)
178
+ # my_mock.stub!(:sym).and_raise(error)
179
+ # my_mock.stub!(:sym).and_throw(:sym)
180
+ # my_mock.stub!(:sym).and_yield([array,of,values,to,yield])
181
+ #
182
+ # == Arbitrary Handling
183
+ #
184
+ # Once in a while you'll find that the available expectations don't solve the
185
+ # particular problem you are trying to solve. Imagine that you expect the message
186
+ # to come with an Array argument that has a specific length, but you don't care
187
+ # what is in it. You could do this:
188
+ #
189
+ # my_mock.should_receive(:sym) do |arg|
190
+ # arg.should be_an_istance_of(Array)
191
+ # arg.length.should == 7
192
+ # end
193
+ #
194
+ # Note that this would fail if the number of arguments received was different from
195
+ # the number of block arguments (in this case 1).
196
+ #
197
+ # == Combining Expectation Details
198
+ #
199
+ # Combining the message name with specific arguments, receive counts and responses
200
+ # you can get quite a bit of detail in your expectations:
201
+ #
202
+ # my_mock.should_receive(:<<).with("illegal value").once.and_raise(ArgumentError)
203
+ module Mocks
204
+ # Shortcut for creating an instance of Spec::Mocks::Mock.
205
+ def mock(name, options={})
206
+ Spec::Mocks::Mock.new(name, options)
207
+ end
208
+
209
+ # Shortcut for creating an instance of Spec::Mocks::Mock with
210
+ # predefined method stubs.
211
+ #
212
+ # == Examples
213
+ #
214
+ # stub_thing = stub("thing", :a => "A")
215
+ # stub_thing.a == "A" => true
216
+ #
217
+ # stub_person = stub("thing", :name => "Joe", :email => "joe@domain.com")
218
+ # stub_person.name => "Joe"
219
+ # stub_person.email => "joe@domain.com"
220
+ def stub(name, stubs={})
221
+ object_stub = mock(name)
222
+ stubs.each { |key, value| object_stub.stub!(key).and_return(value) }
223
+ object_stub
224
+ end
225
+
226
+ # Shortcut for creating an instance of Spec::Mocks::DuckTypeArgConstraint
227
+ def duck_type(*args)
228
+ return Spec::Mocks::DuckTypeArgConstraint.new(*args)
229
+ end
230
+
231
+ end
232
+ end
@@ -1,6 +1,16 @@
1
1
  module Spec
2
2
  module Mocks
3
3
 
4
+ class MatcherConstraint
5
+ def initialize(matcher)
6
+ @matcher = matcher
7
+ end
8
+
9
+ def matches?(value)
10
+ @matcher.matches?(value)
11
+ end
12
+ end
13
+
4
14
  class LiteralArgConstraint
5
15
  def initialize(literal)
6
16
  @literal_value = literal
@@ -79,7 +89,7 @@ module Spec
79
89
  @@constraint_classes[:string] = StringArgConstraint
80
90
 
81
91
  def initialize(args)
82
- @args = *args
92
+ @args = args
83
93
  if [:any_args] == args then @expected_params = nil
84
94
  elsif [:no_args] == args then @expected_params = []
85
95
  else @expected_params = process_arg_constraints(args)
@@ -95,9 +105,13 @@ module Spec
95
105
  def convert_constraint(constraint)
96
106
  return @@constraint_classes[constraint].new(constraint) if constraint.is_a?(Symbol)
97
107
  return constraint if constraint.is_a?(DuckTypeArgConstraint)
108
+ return MatcherConstraint.new(constraint) if is_matcher?(constraint)
98
109
  return RegexpArgConstraint.new(constraint) if constraint.is_a?(Regexp)
99
110
  return LiteralArgConstraint.new(constraint)
100
-
111
+ end
112
+
113
+ def is_matcher?(obj)
114
+ return obj.respond_to?(:matches?) && obj.respond_to?(:failure_message)
101
115
  end
102
116
 
103
117
  def check_args(args)
@@ -58,13 +58,15 @@ module Spec
58
58
  end
59
59
 
60
60
  def format_args(*args)
61
- return "(no args)" if args.empty? || args == :no_args || args == [:no_args]
62
- return "(any args)" if [:any_args] == args
61
+ return "(no args)" if args.empty? || args == [:no_args]
62
+ return "(any args)" if args == [:any_args]
63
63
  "(" + arg_list(*args) + ")"
64
64
  end
65
65
 
66
66
  def arg_list(*args)
67
- args.collect{|arg| arg.inspect}.join(", ")
67
+ args.collect do |arg|
68
+ arg.respond_to?(:description) ? arg.description : arg.inspect
69
+ end.join(", ")
68
70
  end
69
71
 
70
72
  def count_message(count)
@@ -1,9 +1,9 @@
1
1
  module Spec
2
2
  module Mocks
3
- class MockExpectationError < Expectations::ExpectationNotMetError
3
+ class MockExpectationError < StandardError
4
4
  end
5
5
 
6
- class AmbiguousReturnError < Expectations::ExpectationNotMetError
6
+ class AmbiguousReturnError < StandardError
7
7
  end
8
8
  end
9
9
  end
@@ -1,3 +1,3 @@
1
1
  class Object
2
- include Spec::Mocks::MockMethods
2
+ include Spec::Mocks::Methods
3
3
  end
@@ -36,7 +36,8 @@ module Spec
36
36
  else
37
37
  value = values
38
38
  @consecutive = true
39
- @expected_received_count = values.size if @expected_received_count < values.size
39
+ @expected_received_count = values.size if @expected_received_count != :any &&
40
+ @expected_received_count < values.size
40
41
  end
41
42
  @return_block = block_given? ? return_block : lambda { value }
42
43
  end
@@ -82,11 +83,13 @@ module Spec
82
83
  @received_count += 1
83
84
  end
84
85
  end
86
+
87
+ protected
85
88
 
86
89
  def invoke_method_block(args)
87
90
  begin
88
91
  @method_block.call(*args)
89
- rescue Spec::Expectations::ExpectationNotMetError => detail
92
+ rescue => detail
90
93
  @error_generator.raise_block_failed_error @sym, detail.message
91
94
  end
92
95
  end
@@ -118,7 +121,7 @@ module Spec
118
121
  end
119
122
 
120
123
  class MessageExpectation < BaseExpectation
121
-
124
+
122
125
  def matches_name_but_not_args(sym, args)
123
126
  @sym == sym and not @args_expectation.check_args(args)
124
127
  end
@@ -130,14 +133,15 @@ module Spec
130
133
  return if @expected_received_count == @received_count
131
134
 
132
135
  begin
133
- @error_generator.raise_expectation_error @sym, @expected_received_count, @received_count, @args_expectation.args
136
+ @error_generator.raise_expectation_error(@sym, @expected_received_count, @received_count, *@args_expectation.args)
134
137
  rescue => error
135
138
  error.backtrace.insert(0, @expected_from)
136
139
  Kernel::raise error
137
140
  end
138
141
  end
139
142
 
140
- def with(*args)
143
+ def with(*args, &block)
144
+ @method_block = block if block
141
145
  @args_expectation = ArgumentExpectation.new(args)
142
146
  self
143
147
  end
@@ -156,21 +160,14 @@ module Spec
156
160
  set_expected_received_count :at_most, n
157
161
  self
158
162
  end
159
-
160
- def set_expected_received_count(relativity, n)
161
- @at_least = (relativity == :at_least)
162
- @at_most = (relativity == :at_most)
163
- @expected_received_count = 1 if n == :once
164
- @expected_received_count = 2 if n == :twice
165
- @expected_received_count = n if n.kind_of? Numeric
166
- end
167
163
 
168
- def times
169
- #pure sugar
164
+ def times(&block)
165
+ @method_block = block if block
170
166
  self
171
167
  end
172
168
 
173
- def any_number_of_times
169
+ def any_number_of_times(&block)
170
+ @method_block = block if block
174
171
  @expected_received_count = :any
175
172
  self
176
173
  end
@@ -180,17 +177,20 @@ module Spec
180
177
  self
181
178
  end
182
179
 
183
- def once
180
+ def once(&block)
181
+ @method_block = block if block
184
182
  @expected_received_count = 1
185
183
  self
186
184
  end
187
185
 
188
- def twice
186
+ def twice(&block)
187
+ @method_block = block if block
189
188
  @expected_received_count = 2
190
189
  self
191
190
  end
192
191
 
193
- def ordered
192
+ def ordered(&block)
193
+ @method_block = block if block
194
194
  @order_group.register(self)
195
195
  @ordered = true
196
196
  self
@@ -199,6 +199,16 @@ module Spec
199
199
  def negative_expectation_for?(sym)
200
200
  return false
201
201
  end
202
+
203
+ protected
204
+ def set_expected_received_count(relativity, n)
205
+ @at_least = (relativity == :at_least)
206
+ @at_most = (relativity == :at_most)
207
+ @expected_received_count = 1 if n == :once
208
+ @expected_received_count = 2 if n == :twice
209
+ @expected_received_count = n if n.kind_of? Numeric
210
+ end
211
+
202
212
  end
203
213
 
204
214
  class NegativeMessageExpectation < MessageExpectation
@@ -1,6 +1,6 @@
1
1
  module Spec
2
2
  module Mocks
3
- module MockMethods
3
+ module Methods
4
4
  def should_receive(sym, opts={}, &block)
5
5
  __mock_handler.add_message_expectation(opts[:expected_from] || caller(1)[0], sym, opts, &block)
6
6
  end
@@ -13,19 +13,19 @@ module Spec
13
13
  __mock_handler.add_stub(caller(1)[0], sym)
14
14
  end
15
15
 
16
- def received_message?(sym, *args, &block)
16
+ def received_message?(sym, *args, &block) #:nodoc:
17
17
  __mock_handler.received_message?(sym, *args, &block)
18
18
  end
19
19
 
20
- def __verify
20
+ def __verify #:nodoc:
21
21
  __mock_handler.verify
22
22
  end
23
23
 
24
- def __reset_mock
24
+ def __reset_mock #:nodoc:
25
25
  __mock_handler.reset
26
26
  end
27
27
 
28
- def method_missing(sym, *args, &block)
28
+ def method_missing(sym, *args, &block) #:nodoc:
29
29
  __mock_handler.instance_eval {@messages_received << [sym, args, block]}
30
30
  super(sym, *args, &block)
31
31
  end