rr 0.4.10 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. data/CHANGES +14 -0
  2. data/README.rdoc +67 -13
  3. data/Rakefile +1 -1
  4. data/lib/rr.rb +29 -9
  5. data/lib/rr/adapters/rr_methods.rb +38 -158
  6. data/lib/rr/double.rb +46 -41
  7. data/lib/rr/double_definitions/child_double_definition_creator.rb +23 -0
  8. data/lib/rr/double_definitions/double_definition.rb +212 -0
  9. data/lib/rr/double_definitions/double_definition_creator.rb +153 -0
  10. data/lib/rr/double_definitions/double_definition_creator_proxy.rb +25 -0
  11. data/lib/rr/double_definitions/strategies/implementation/implementation_strategy.rb +15 -0
  12. data/lib/rr/double_definitions/strategies/implementation/proxy.rb +62 -0
  13. data/lib/rr/double_definitions/strategies/implementation/reimplementation.rb +14 -0
  14. data/lib/rr/double_definitions/strategies/scope/instance.rb +15 -0
  15. data/lib/rr/double_definitions/strategies/scope/instance_of_class.rb +43 -0
  16. data/lib/rr/double_definitions/strategies/scope/scope_strategy.rb +15 -0
  17. data/lib/rr/double_definitions/strategies/strategy.rb +70 -0
  18. data/lib/rr/double_definitions/strategies/verification/dont_allow.rb +34 -0
  19. data/lib/rr/double_definitions/strategies/verification/mock.rb +44 -0
  20. data/lib/rr/double_definitions/strategies/verification/stub.rb +45 -0
  21. data/lib/rr/double_definitions/strategies/verification/verification_strategy.rb +15 -0
  22. data/lib/rr/double_injection.rb +21 -15
  23. data/lib/rr/expectations/argument_equality_expectation.rb +2 -1
  24. data/lib/rr/space.rb +23 -22
  25. data/lib/rr/wildcard_matchers/hash_including.rb +29 -0
  26. data/lib/rr/wildcard_matchers/satisfy.rb +26 -0
  27. data/spec/high_level_spec.rb +111 -64
  28. data/spec/rr/adapters/rr_methods_argument_matcher_spec.rb +1 -1
  29. data/spec/rr/adapters/rr_methods_creator_spec.rb +99 -315
  30. data/spec/rr/adapters/rr_methods_space_spec.rb +90 -109
  31. data/spec/rr/adapters/rr_methods_spec_helper.rb +1 -1
  32. data/spec/rr/adapters/rr_methods_times_matcher_spec.rb +1 -1
  33. data/spec/rr/double_definitions/child_double_definition_creator_spec.rb +103 -0
  34. data/spec/rr/double_definitions/double_definition_creator_proxy_spec.rb +83 -0
  35. data/spec/rr/double_definitions/double_definition_creator_spec.rb +495 -0
  36. data/spec/rr/double_definitions/double_definition_spec.rb +1116 -0
  37. data/spec/rr/double_injection/double_injection_bind_spec.rb +111 -0
  38. data/spec/rr/double_injection/double_injection_dispatching_spec.rb +245 -0
  39. data/spec/rr/{double → double_injection}/double_injection_has_original_method_spec.rb +9 -9
  40. data/spec/rr/double_injection/double_injection_reset_spec.rb +90 -0
  41. data/spec/rr/double_injection/double_injection_spec.rb +77 -0
  42. data/spec/rr/double_injection/double_injection_verify_spec.rb +29 -0
  43. data/spec/rr/double_spec.rb +156 -136
  44. data/spec/rr/errors/rr_error_spec.rb +1 -1
  45. data/spec/rr/expectations/any_argument_expectation_spec.rb +1 -1
  46. data/spec/rr/expectations/anything_argument_equality_expectation_spec.rb +6 -30
  47. data/spec/rr/expectations/argument_equality_expectation_spec.rb +35 -18
  48. data/spec/rr/expectations/boolean_argument_equality_expectation_spec.rb +22 -41
  49. data/spec/rr/expectations/hash_including_argument_equality_expectation_spec.rb +82 -0
  50. data/spec/rr/expectations/hash_including_spec.rb +17 -0
  51. data/spec/rr/expectations/satisfy_argument_equality_expectation_spec.rb +59 -0
  52. data/spec/rr/expectations/satisfy_spec.rb +14 -0
  53. data/spec/rr/expectations/times_called_expectation/times_called_expectation_any_times_spec.rb +30 -28
  54. data/spec/rr/expectations/times_called_expectation/times_called_expectation_at_least_spec.rb +55 -54
  55. data/spec/rr/expectations/times_called_expectation/times_called_expectation_at_most_spec.rb +49 -48
  56. data/spec/rr/expectations/times_called_expectation/times_called_expectation_helper.rb +9 -7
  57. data/spec/rr/expectations/times_called_expectation/times_called_expectation_integer_spec.rb +77 -76
  58. data/spec/rr/expectations/times_called_expectation/times_called_expectation_proc_spec.rb +58 -57
  59. data/spec/rr/expectations/times_called_expectation/times_called_expectation_range_spec.rb +59 -58
  60. data/spec/rr/expectations/times_called_expectation/times_called_expectation_spec.rb +25 -24
  61. data/spec/rr/rspec/rspec_adapter_spec.rb +12 -11
  62. data/spec/rr/rspec/rspec_backtrace_tweaking_spec.rb +10 -8
  63. data/spec/rr/rspec/rspec_usage_spec.rb +1 -1
  64. data/spec/rr/space/hash_with_object_id_key_spec.rb +1 -1
  65. data/spec/rr/space/space_spec.rb +330 -192
  66. data/spec/rr/test_unit/test_helper.rb +1 -2
  67. data/spec/rr/test_unit/test_unit_backtrace_test.rb +1 -2
  68. data/spec/rr/test_unit/test_unit_integration_test.rb +1 -2
  69. data/spec/rr/times_called_matchers/any_times_matcher_spec.rb +1 -1
  70. data/spec/rr/times_called_matchers/at_least_matcher_spec.rb +1 -1
  71. data/spec/rr/times_called_matchers/at_most_matcher_spec.rb +1 -1
  72. data/spec/rr/times_called_matchers/integer_matcher_spec.rb +1 -1
  73. data/spec/rr/times_called_matchers/proc_matcher_spec.rb +1 -1
  74. data/spec/rr/times_called_matchers/range_matcher_spec.rb +1 -1
  75. data/spec/rr/times_called_matchers/times_called_matcher_spec.rb +1 -1
  76. data/spec/rr/wildcard_matchers/anything_spec.rb +24 -0
  77. data/spec/rr/wildcard_matchers/boolean_spec.rb +36 -0
  78. data/spec/rr/wildcard_matchers/duck_type_spec.rb +52 -0
  79. data/spec/rr/wildcard_matchers/is_a_spec.rb +32 -0
  80. data/spec/rr/wildcard_matchers/numeric_spec.rb +32 -0
  81. data/spec/rr/wildcard_matchers/range_spec.rb +35 -0
  82. data/spec/rr/wildcard_matchers/regexp_spec.rb +43 -0
  83. data/spec/rr_spec.rb +28 -0
  84. data/spec/spec_helper.rb +84 -0
  85. metadata +43 -29
  86. data/lib/rr/double_creator.rb +0 -271
  87. data/lib/rr/double_definition.rb +0 -179
  88. data/lib/rr/double_definition_builder.rb +0 -44
  89. data/lib/rr/double_definition_creator.rb +0 -156
  90. data/lib/rr/double_definition_creator_proxy.rb +0 -20
  91. data/spec/rr/double/double_injection_bind_spec.rb +0 -105
  92. data/spec/rr/double/double_injection_dispatching_spec.rb +0 -228
  93. data/spec/rr/double/double_injection_reset_spec.rb +0 -86
  94. data/spec/rr/double/double_injection_spec.rb +0 -72
  95. data/spec/rr/double/double_injection_verify_spec.rb +0 -24
  96. data/spec/rr/double_definition_creator_proxy_spec.rb +0 -85
  97. data/spec/rr/double_definition_creator_spec.rb +0 -496
  98. data/spec/rr/double_definition_spec.rb +0 -815
  99. data/spec/rr/expectations/anything_spec.rb +0 -14
  100. data/spec/rr/expectations/boolean_spec.rb +0 -14
  101. data/spec/rr/expectations/duck_type_argument_equality_expectation_spec.rb +0 -71
  102. data/spec/rr/expectations/duck_type_spec.rb +0 -14
  103. data/spec/rr/expectations/is_a_argument_equality_expectation_spec.rb +0 -51
  104. data/spec/rr/expectations/is_a_spec.rb +0 -14
  105. data/spec/rr/expectations/numeric_argument_equality_expectation_spec.rb +0 -47
  106. data/spec/rr/expectations/numeric_spec.rb +0 -14
  107. data/spec/rr/expectations/range_argument_equality_expectation_spec.rb +0 -59
  108. data/spec/rr/expectations/range_spec.rb +0 -10
  109. data/spec/rr/expectations/regexp_argument_equality_expectation_spec.rb +0 -72
  110. data/spec/rr/expectations/regexp_spec.rb +0 -10
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