rr 0.4.10 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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
data/CHANGES CHANGED
@@ -1,3 +1,17 @@
1
+ * 0.6.0
2
+ - Friendlier DoubleNotFound error message
3
+ - Implemented Double strategy creation methods (#mock, #stub, #proxy, #instance_of, and ! equivalents) on DoubleDefinition
4
+ - Implemented hash_including matcher (Patch by Matthew O'Conner)
5
+ - Implemented satisfy matcher (Patch by Matthew O'Conner)
6
+ - Implemented DoubleDefinitionCreator#mock!, #stub!, and #dont_allow!
7
+ - Modified api to method chain Doubles
8
+ - Fix conflict with Mocha overriding Object#verify
9
+
10
+ * 0.5.0
11
+ - Method chaining Doubles (Patch by Nick Kallen)
12
+ - Chained ordered expectations (Patch by Nick Kallen)
13
+ - Space#verify_doubles can take one or more objects with DoubleInjections to be verified
14
+
1
15
  * 0.4.10
2
16
  - DoubleDefinitionCreatorProxy does not undef #object_id
3
17
  - Fixed rdoc pointer to README
@@ -3,6 +3,15 @@
3
3
  RR (Double Ruby) is a test double framework that features a rich
4
4
  selection of double techniques and a terse syntax.
5
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
+
6
15
  == What is a Test Double?
7
16
  A Test Double is a generalization of something that replaces a real
8
17
  object to make it easier to test another object. Its like a stunt
@@ -33,7 +42,7 @@ support spies.
33
42
  == Syntax between RR and other double/mock frameworks
34
43
  === Terse Syntax
35
44
  One of the goals of RR is to make doubles more scannable.
36
- This is accomplished by removing words from a double declaration.
45
+ This is accomplished by making the double declaration look as much as the actual method invocation as possible.
37
46
  Here is RR compared to other mock frameworks:
38
47
 
39
48
  flexmock(User).should_receive(:find).with('42').and_return(jane) # Flexmock
@@ -42,10 +51,8 @@ Here is RR compared to other mock frameworks:
42
51
  User.should_receive(:find).with('42') {jane} # Rspec using return value blocks
43
52
  mock(User).find('42') {jane} # RR
44
53
 
45
- === No "pure" mock object
46
- RR is an opinionated framework. RR does not create a mock object for you,
47
- like other frameworks. Instead, RR utilizes a technique known as
48
- "double injection".
54
+ === Double Injections (a.k.a Partial Mocking)
55
+ RR utilizes a technique known as "double injection".
49
56
 
50
57
  my_object = MyClass.new
51
58
  mock(my_object).hello
@@ -54,10 +61,14 @@ Compare this with doing a mock in mocha:
54
61
  my_mocked_object = mock()
55
62
  my_mocked_object.expects(:hello)
56
63
 
64
+ == Pure Mock objects
57
65
  If you wish to use objects for the sole purpose of being a mock, you can
58
66
  do so by creating an empty object.
59
67
  mock(my_mock_object = Object.new).hello
60
68
 
69
+ or by using mock!
70
+ my_mock_object = mock!.hello.subject # Mocks the #hello method and retrieves that object via the #subject method
71
+
61
72
  === No should_receive or expects method
62
73
  RR uses method_missing to set your method expectation. This means you do not
63
74
  need to use a method such as should_receive or expects.
@@ -70,7 +81,7 @@ Rspec mocks:
70
81
  my_object.should_receive(:hello) # should_receive sets the hello method expectation
71
82
 
72
83
  === with method call is not necessary
73
- Since RR uses method_missing, it also make using the with method unnecessary
84
+ Since RR uses method_missing, it also makes using the #with method unnecessary in most circumstances
74
85
  to set the argument expectations.
75
86
 
76
87
  mock(my_object).hello('bob', 'jane')
@@ -95,16 +106,19 @@ Rspec mocks:
95
106
 
96
107
  == Using RR
97
108
  To create a double on an object, you can use the following methods:
98
- * mock
99
- * stub
100
- * proxy
101
- * instance_of
109
+ * mock or mock!
110
+ * stub or stub!
111
+ * dont_allow or dont_allow!
112
+ * proxy or proxy!
113
+ * instance_of or instance_of!
102
114
 
103
- These methods are composable. mock and stub can be used by themselves and
115
+ These methods are composable. mock, stub, and dont_allow can be used by themselves and
104
116
  are mutually exclusive.
105
- proxy and instance_of must be chained with mock or stub. You can chain
117
+ proxy and instance_of must be chained with mock or stub. You can also chain
106
118
  proxy and instance_of together.
107
119
 
120
+ The ! (bang) version of these methods causes the subject object of the Double to be instantiated.
121
+
108
122
  === mock
109
123
  mock replaces the method on the object with an expectation and implementation.
110
124
  The expectations are a mock will be called with certain arguments a certain
@@ -136,6 +150,12 @@ an exception is raised.
136
150
  raise "Unexpected id #{id.inspect} passed to me"
137
151
  end
138
152
 
153
+ === dont_allow - aliased with do_not_allow, dont_call, and do_not_call
154
+ dont_allow sets an expectation on the Double that it will never be called.
155
+ If the Double is called, then a TimesCalledError is raised.
156
+ dont_allow(User).find('42')
157
+ User.find('42') # raises a TimesCalledError
158
+
139
159
  === mock.proxy
140
160
  mock.proxy replaces the method on the object with an expectation, implementation, and
141
161
  also invokes the actual method. mock.proxy also intercepts the return value and
@@ -190,6 +210,22 @@ Put double scenarios on instances of a Class.
190
210
  m.system("rake baz") {true}
191
211
  end
192
212
 
213
+ === Double Graphs
214
+ RR has a method-chaining api support for Double graphs. For example,
215
+ lets say you want an object to receive a method call to #foo, and have
216
+ the return value receive a method call to #bar.
217
+
218
+ In RR, you would do:
219
+ stub(object).foo.stub!.bar {:baz}
220
+ object.foo.bar # :baz
221
+ # or
222
+ stub(object).foo {stub!.bar {:baz}}
223
+ object.foo.bar # :baz
224
+ # or
225
+ bar = stub!.bar {:baz}
226
+ stub(object).foo {bar}
227
+ object.foo.bar # :baz
228
+
193
229
  === Argument Wildcard matchers
194
230
  ==== anything
195
231
  mock(object).foobar(1, anything)
@@ -214,6 +250,22 @@ Put double scenarios on instances of a Class.
214
250
  def arg.talk; 'quack'; end
215
251
  object.foobar(arg)
216
252
 
253
+ ==== Ranges
254
+ mock(object).foobar(1..10)
255
+ object.foobar(5)
256
+
257
+ ==== Regexps
258
+ mock(object).foobar(/on/)
259
+ object.foobar("ruby on rails")
260
+
261
+ ==== hash_including
262
+ mock(object).foobar(hash_including(:red => "#FF0000", :blue => "#0000FF"))
263
+ object.foobar({:red => "#FF0000", :blue => "#0000FF", :green => "#00FF00"})
264
+
265
+ ==== satisfy
266
+ mock(object).foobar(satisfy {|arg| arg.length == 2})
267
+ object.foobar("xy")
268
+
217
269
  === Invocation Amount Wildcard Matchers
218
270
  ==== any_times
219
271
  mock(object).method_name(anything).times(any_times) {return_value}
@@ -222,10 +274,12 @@ Put double scenarios on instances of a Class.
222
274
  With any development effort, there are countless people who have contributed
223
275
  to making it possible. We all are standing on the shoulders of giants.
224
276
  * Pivotal Labs for sponsoring RR development
277
+ * Nick Kallen for documentation suggestions, bug reports, and patches
278
+ * Matthew O'Conner for patches
279
+ * Nathan Sobo for various ideas and inspiration for cleaner and more expressive code
225
280
  * Parker Thompson for pairing with me
226
281
  * Felix Morio for pairing with me
227
282
  * Jeff Whitmire for documentation suggestions
228
- * Nick Kallen for documentation suggestion & bug reports
229
283
  * David Chelimsky for encouragement to make the RR framework, for developing
230
284
  the Rspec mock framework, and syntax ideas
231
285
  * Gerard Meszaros for his excellent book "xUnit Test Patterns"
data/Rakefile CHANGED
@@ -26,7 +26,7 @@ def run_suite
26
26
  end
27
27
 
28
28
  PKG_NAME = "rr"
29
- PKG_VERSION = "0.4.10"
29
+ PKG_VERSION = "0.6.0"
30
30
  PKG_FILES = FileList[
31
31
  '[A-Z]*',
32
32
  '*.rb',
data/lib/rr.rb CHANGED
@@ -10,13 +10,24 @@ require "#{dir}/rr/space"
10
10
  require "#{dir}/rr/double_injection"
11
11
  require "#{dir}/rr/hash_with_object_id_key"
12
12
 
13
- require "#{dir}/rr/double_definition_creator_proxy"
14
-
15
- require "#{dir}/rr/double_definition_creator"
13
+ require "#{dir}/rr/double_definitions/double_definition_creator_proxy"
14
+ require "#{dir}/rr/double_definitions/double_definition_creator"
15
+ require "#{dir}/rr/double_definitions/child_double_definition_creator"
16
+ require "#{dir}/rr/adapters/rr_methods"
16
17
 
17
18
  require "#{dir}/rr/double"
18
- require "#{dir}/rr/double_definition"
19
- require "#{dir}/rr/double_definition_builder"
19
+ require "#{dir}/rr/double_definitions/double_definition"
20
+ require "#{dir}/rr/double_definitions/strategies/strategy"
21
+ require "#{dir}/rr/double_definitions/strategies/verification/verification_strategy"
22
+ require "#{dir}/rr/double_definitions/strategies/verification/mock"
23
+ require "#{dir}/rr/double_definitions/strategies/verification/stub"
24
+ require "#{dir}/rr/double_definitions/strategies/verification/dont_allow"
25
+ require "#{dir}/rr/double_definitions/strategies/implementation/implementation_strategy"
26
+ require "#{dir}/rr/double_definitions/strategies/implementation/reimplementation"
27
+ require "#{dir}/rr/double_definitions/strategies/implementation/proxy"
28
+ require "#{dir}/rr/double_definitions/strategies/scope/scope_strategy"
29
+ require "#{dir}/rr/double_definitions/strategies/scope/instance"
30
+ require "#{dir}/rr/double_definitions/strategies/scope/instance_of_class"
20
31
  require "#{dir}/rr/double_matches"
21
32
 
22
33
  require "#{dir}/rr/expectations/argument_equality_expectation"
@@ -30,6 +41,8 @@ require "#{dir}/rr/wildcard_matchers/boolean"
30
41
  require "#{dir}/rr/wildcard_matchers/duck_type"
31
42
  require "#{dir}/rr/wildcard_matchers/regexp"
32
43
  require "#{dir}/rr/wildcard_matchers/range"
44
+ require "#{dir}/rr/wildcard_matchers/satisfy"
45
+ require "#{dir}/rr/wildcard_matchers/hash_including"
33
46
 
34
47
  require "#{dir}/rr/times_called_matchers/terminal"
35
48
  require "#{dir}/rr/times_called_matchers/non_terminal"
@@ -41,15 +54,22 @@ require "#{dir}/rr/times_called_matchers/proc_matcher"
41
54
  require "#{dir}/rr/times_called_matchers/at_least_matcher"
42
55
  require "#{dir}/rr/times_called_matchers/at_most_matcher"
43
56
 
44
- require "#{dir}/rr/adapters/rr_methods"
45
-
46
57
  require "#{dir}/rr/adapters/rspec"
47
58
  require "#{dir}/rr/adapters/test_unit"
48
59
 
49
60
  module RR
50
61
  class << self
62
+ (RR::Space.instance_methods - Object.instance_methods).each do |method_name|
63
+ returns_method = <<-METHOD
64
+ def #{method_name}(*args, &block)
65
+ RR::Space.instance.__send__(:#{method_name}, *args, &block)
66
+ end
67
+ METHOD
68
+ class_eval(returns_method, __FILE__, __LINE__ - 4)
69
+ end
70
+
51
71
  def method_missing(method_name, *args, &block)
52
72
  RR::Space.instance.__send__(method_name, *args, &block)
53
73
  end
54
- end
55
- end
74
+ end
75
+ end
@@ -1,6 +1,24 @@
1
1
  module RR
2
2
  module Adapters
3
3
  module RRMethods
4
+ class << self
5
+ def register_strategy_class(strategy_class, method_name)
6
+ class_eval((<<-CLASS), __FILE__, __LINE__ + 1)
7
+ def #{method_name}(subject=DoubleDefinitions::DoubleDefinitionCreator::NO_SUBJECT, method_name=nil, &definition_eval_block)
8
+ creator = DoubleDefinitions::DoubleDefinitionCreator.new
9
+ creator.#{method_name}(subject, method_name, &definition_eval_block)
10
+ end
11
+ CLASS
12
+
13
+ class_eval((<<-CLASS), __FILE__, __LINE__ + 1)
14
+ def #{method_name}!(method_name=nil, &definition_eval_block)
15
+ creator = DoubleDefinitions::DoubleDefinitionCreator.new
16
+ creator.#{method_name}!(method_name, &definition_eval_block)
17
+ end
18
+ CLASS
19
+ end
20
+ end
21
+
4
22
  # Verifies all the DoubleInjection objects have met their
5
23
  # TimesCalledExpectations.
6
24
  def verify
@@ -12,163 +30,6 @@ module RR
12
30
  RR::Space.instance.reset
13
31
  end
14
32
 
15
- # This method sets the Double to have a mock strategy. A mock strategy
16
- # sets the default state of the Double to expect the method call
17
- # with arguments exactly one time. The Double's expectations can be
18
- # changed.
19
- #
20
- # This method can be chained with proxy.
21
- # mock.proxy(subject).method_name_1
22
- # or
23
- # proxy.mock(subject).method_name_1
24
- #
25
- # When passed the subject, a DoubleDefinitionCreatorProxy is returned. Passing
26
- # a method with arguments to the proxy will set up expectations that
27
- # the a call to the subject's method with the arguments will happen,
28
- # and return the prescribed value.
29
- # mock(subject).method_name_1 {return_value_1}
30
- # mock(subject).method_name_2(arg1, arg2) {return_value_2}
31
- #
32
- # When passed the subject and the method_name, this method returns
33
- # a mock Double with the method already set.
34
- #
35
- # mock(subject, :method_name_1) {return_value_1}
36
- # mock(subject, :method_name_2).with(arg1, arg2) {return_value_2}
37
- #
38
- # mock also takes a block for definitions.
39
- # mock(subject) do
40
- # method_name_1 {return_value_1}
41
- # method_name_2(arg_1, arg_2) {return_value_2}
42
- # end
43
- def mock(subject=DoubleDefinitionCreator::NO_SUBJECT_ARG, method_name=nil, &definition)
44
- creator = DoubleDefinitionCreator.new
45
- creator.mock(subject, method_name, &definition)
46
- end
47
-
48
-
49
- # This method sets the Double to have a stub strategy. A stub strategy
50
- # sets the default state of the Double to expect the method call
51
- # with any arguments any number of times. The Double's
52
- # expectations can be changed.
53
- #
54
- # This method can be chained with proxy.
55
- # stub.proxy(subject).method_name_1
56
- # or
57
- # proxy.stub(subject).method_name_1
58
- #
59
- # When passed the subject, a DoubleDefinitionCreatorProxy is returned. Passing
60
- # a method with arguments to the proxy will set up expectations that
61
- # the a call to the subject's method with the arguments will happen,
62
- # and return the prescribed value.
63
- # stub(subject).method_name_1 {return_value_1}
64
- # stub(subject).method_name_2(arg_1, arg_2) {return_value_2}
65
- #
66
- # When passed the subject and the method_name, this method returns
67
- # a stub Double with the method already set.
68
- #
69
- # mock(subject, :method_name_1) {return_value_1}
70
- # mock(subject, :method_name_2).with(arg1, arg2) {return_value_2}
71
- #
72
- # stub also takes a block for definitions.
73
- # stub(subject) do
74
- # method_name_1 {return_value_1}
75
- # method_name_2(arg_1, arg_2) {return_value_2}
76
- # end
77
- def stub(subject=DoubleDefinitionCreator::NO_SUBJECT_ARG, method_name=nil, &definition)
78
- creator = DoubleDefinitionCreator.new
79
- creator.stub(subject, method_name, &definition)
80
- end
81
-
82
- # This method add proxy capabilities to the Double. proxy can be called
83
- # with mock or stub.
84
- #
85
- # mock.proxy(controller.template).render(:partial => "my/socks")
86
- #
87
- # stub.proxy(controller.template).render(:partial => "my/socks") do |html|
88
- # html.should include("My socks are wet")
89
- # html
90
- # end
91
- #
92
- # mock.proxy(controller.template).render(:partial => "my/socks") do |html|
93
- # html.should include("My socks are wet")
94
- # "My new return value"
95
- # end
96
- #
97
- # mock.proxy also takes a block for definitions.
98
- # mock.proxy(subject) do
99
- # render(:partial => "my/socks")
100
- #
101
- # render(:partial => "my/socks") do |html|
102
- # html.should include("My socks are wet")
103
- # html
104
- # end
105
- #
106
- # render(:partial => "my/socks") do |html|
107
- # html.should include("My socks are wet")
108
- # html
109
- # end
110
- #
111
- # render(:partial => "my/socks") do |html|
112
- # html.should include("My socks are wet")
113
- # "My new return value"
114
- # end
115
- # end
116
- #
117
- # Passing a block to the Double (after the method name and arguments)
118
- # allows you to intercept the return value.
119
- # The return value can be modified, validated, and/or overridden by
120
- # passing in a block. The return value of the block will replace
121
- # the actual return value.
122
- #
123
- # mock.proxy(controller.template).render(:partial => "my/socks") do |html|
124
- # html.should include("My socks are wet")
125
- # "My new return value"
126
- # end
127
- def proxy(subject=DoubleDefinitionCreator::NO_SUBJECT_ARG, method_name=nil, &definition)
128
- creator = DoubleDefinitionCreator.new
129
- creator.proxy(subject, method_name, &definition)
130
- end
131
-
132
- # This method sets the Double to have a dont_allow strategy.
133
- # A dont_allow strategy sets the default state of the Double
134
- # to expect never to be called. The Double's expectations can be
135
- # changed.
136
- #
137
- # The following example sets the expectation that subject.method_name
138
- # will never be called with arg1 and arg2.
139
- #
140
- # do_not_allow(subject).method_name(arg1, arg2)
141
- #
142
- # dont_allow also supports a block sytnax.
143
- # dont_allow(subject) do |m|
144
- # m.method1 # Do not allow method1 with any arguments
145
- # m.method2(arg1, arg2) # Do not allow method2 with arguments arg1 and arg2
146
- # m.method3.with_no_args # Do not allow method3 with no arguments
147
- # end
148
- def dont_allow(subject=DoubleDefinitionCreator::NO_SUBJECT_ARG, method_name=nil, &definition)
149
- creator = DoubleDefinitionCreator.new
150
- creator.dont_allow(subject, method_name, &definition)
151
- end
152
- alias_method :do_not_allow, :dont_allow
153
- alias_method :dont_call, :dont_allow
154
- alias_method :do_not_call, :dont_allow
155
-
156
- # Calling instance_of will cause all instances of the passed in Class
157
- # to have the Double defined.
158
- #
159
- # The following example mocks all User's valid? method and return false.
160
- # mock.instance_of(User).valid? {false}
161
- #
162
- # The following example mocks and proxies User#projects and returns the
163
- # first 3 projects.
164
- # mock.instance_of(User).projects do |projects|
165
- # projects[0..2]
166
- # end
167
- def instance_of(subject=DoubleDefinitionCreator::NO_SUBJECT_ARG, method_name=nil, &definition)
168
- creator = DoubleDefinitionCreator.new
169
- creator.instance_of(subject, method_name, &definition)
170
- end
171
-
172
33
  # Returns a AnyTimesMatcher. This is meant to be passed in as an argument
173
34
  # to Double#times.
174
35
  #
@@ -210,7 +71,7 @@ module RR
210
71
  end
211
72
 
212
73
  # Sets up a DuckType wildcard ArgumentEqualityExpectation
213
- # that succeeds when passed the argument implements the methods.
74
+ # that succeeds when the passed argument implements the methods.
214
75
  # arg = Object.new
215
76
  # def arg.foo; end
216
77
  # def arg.bar; end
@@ -219,6 +80,25 @@ module RR
219
80
  def duck_type(*args)
220
81
  RR::WildcardMatchers::DuckType.new(*args)
221
82
  end
83
+
84
+ # Sets up a HashIncluding wildcard ArgumentEqualityExpectation
85
+ # that succeeds when the passed argument contains at least those keys
86
+ # and values of the expectation.
87
+ # mock(object).method_name(hash_including(:foo => 1)) {return_value}
88
+ # object.method_name({:foo => 1, :bar => 2) # passes
89
+ def hash_including(expected_hash)
90
+ RR::WildcardMatchers::HashIncluding.new(expected_hash)
91
+ end
92
+
93
+ # Sets up a Satisfy wildcard ArgumentEqualityExpectation
94
+ # that succeeds when the passed argument causes the expectation's
95
+ # proc to return true.
96
+ # mock(object).method_name(satisfy {|arg| arg == :foo}) {return_value}
97
+ # object.method_name(:foo) # passes
98
+ def satisfy(expectation_proc=nil, &block)
99
+ expectation_proc ||= block
100
+ RR::WildcardMatchers::Satisfy.new(expectation_proc)
101
+ end
222
102
 
223
103
  instance_methods.each do |name|
224
104
  alias_method "rr_#{name}", name