rspec 0.7.5.1 → 0.8.0

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