rr 1.1.1 → 3.0.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 (223) hide show
  1. checksums.yaml +5 -5
  2. data/Appraisals +6 -0
  3. data/CHANGES.md +102 -1
  4. data/CREDITS.md +5 -0
  5. data/Gemfile +3 -0
  6. data/README.md +91 -110
  7. data/Rakefile +43 -0
  8. data/doc/02_syntax_comparison.md +1 -0
  9. data/gemfiles/ruby_19_rspec_2.gemfile +14 -0
  10. data/gemfiles/ruby_19_rspec_2.gemfile.lock +49 -0
  11. data/gemfiles/ruby_19_rspec_2_rails_4.gemfile +15 -0
  12. data/gemfiles/ruby_19_rspec_2_rails_4.gemfile.lock +119 -0
  13. data/lib/rr/class_instance_method_defined.rb +1 -1
  14. data/lib/rr/core_ext/array.rb +2 -0
  15. data/lib/rr/core_ext/hash.rb +2 -0
  16. data/lib/rr/deprecations.rb +97 -0
  17. data/lib/rr/double.rb +28 -10
  18. data/lib/rr/double_definitions/double_definition.rb +39 -16
  19. data/lib/rr/double_definitions/double_definition_create.rb +5 -5
  20. data/lib/rr/double_definitions/double_definition_create_blank_slate.rb +10 -4
  21. data/lib/rr/double_definitions/double_injections/any_instance_of.rb +1 -1
  22. data/lib/rr/double_definitions/double_injections/instance.rb +2 -2
  23. data/lib/rr/double_definitions/strategies/strategy.rb +27 -8
  24. data/lib/rr/double_definitions/strategies/verification/mock.rb +8 -2
  25. data/lib/rr/double_matches.rb +4 -3
  26. data/lib/rr/dsl.rb +152 -0
  27. data/lib/rr/expectations/any_argument_expectation.rb +4 -4
  28. data/lib/rr/expectations/argument_equality_expectation.rb +43 -5
  29. data/lib/rr/injections/double_injection.rb +67 -19
  30. data/lib/rr/injections/method_missing_injection.rb +37 -6
  31. data/lib/rr/integrations.rb +13 -12
  32. data/lib/rr/integrations/decorator.rb +4 -1
  33. data/lib/rr/integrations/minitest_4.rb +1 -1
  34. data/lib/rr/integrations/minitest_4_active_support.rb +1 -1
  35. data/lib/rr/integrations/rspec/invocation_matcher.rb +0 -8
  36. data/lib/rr/integrations/rspec_2.rb +28 -3
  37. data/lib/rr/keyword_arguments.rb +15 -0
  38. data/lib/rr/method_dispatches/base_method_dispatch.rb +22 -5
  39. data/lib/rr/method_dispatches/method_dispatch.rb +21 -10
  40. data/lib/rr/method_dispatches/method_missing_dispatch.rb +14 -5
  41. data/lib/rr/recorded_call.rb +35 -0
  42. data/lib/rr/recorded_calls.rb +23 -9
  43. data/lib/rr/space.rb +15 -5
  44. data/lib/rr/spy_verification.rb +13 -5
  45. data/lib/rr/version.rb +1 -2
  46. data/lib/rr/wildcard_matchers.rb +10 -10
  47. data/lib/rr/without_autohook.rb +7 -14
  48. data/rr.gemspec +14 -5
  49. data/spec/custom_formatter_for_rspec.rb +18 -0
  50. data/spec/custom_formatter_for_rspec_2.rb +40 -0
  51. data/spec/defines_spec_suite_tasks.rb +57 -0
  52. data/spec/fixtures/rubygems_patch_for_187.rb +598 -0
  53. data/spec/global_helper.rb +38 -0
  54. data/spec/spec.opts +3 -0
  55. data/spec/spec_suite_configuration.rb +126 -0
  56. data/spec/spec_suite_runner.rb +47 -0
  57. data/spec/suites.yml +10 -0
  58. data/spec/suites/rspec_2/functional/any_instance_of_spec.rb +147 -0
  59. data/spec/suites/rspec_2/functional/dont_allow_spec.rb +17 -0
  60. data/spec/suites/rspec_2/functional/mock_bang_spec.rb +20 -0
  61. data/spec/suites/rspec_2/functional/mock_instance_of_spec.rb +14 -0
  62. data/spec/suites/rspec_2/functional/mock_instance_of_strong_spec.rb +15 -0
  63. data/spec/suites/rspec_2/functional/mock_proxy_instance_of_spec.rb +15 -0
  64. data/spec/suites/rspec_2/functional/mock_proxy_spec.rb +14 -0
  65. data/spec/suites/rspec_2/functional/mock_spec.rb +17 -0
  66. data/spec/suites/rspec_2/functional/mock_strong_spec.rb +14 -0
  67. data/spec/suites/rspec_2/functional/received_spec.rb +16 -0
  68. data/spec/suites/rspec_2/functional/spy_spec.rb +102 -0
  69. data/spec/suites/rspec_2/functional/stub_bang_spec.rb +20 -0
  70. data/spec/suites/rspec_2/functional/stub_instance_of_spec.rb +15 -0
  71. data/spec/suites/rspec_2/functional/stub_instance_of_strong_spec.rb +15 -0
  72. data/spec/suites/rspec_2/functional/stub_proxy_instance_of_spec.rb +16 -0
  73. data/spec/suites/rspec_2/functional/stub_proxy_spec.rb +45 -0
  74. data/spec/suites/rspec_2/functional/stub_spec.rb +71 -0
  75. data/spec/suites/rspec_2/functional/stub_strong_spec.rb +15 -0
  76. data/spec/suites/rspec_2/functional/wildcard_matchers_spec.rb +128 -0
  77. data/spec/suites/rspec_2/helper.rb +28 -0
  78. data/spec/suites/rspec_2/integration/minitest_4_spec.rb +109 -0
  79. data/spec/suites/rspec_2/integration/minitest_spec.rb +109 -0
  80. data/spec/suites/rspec_2/spec_helper.rb +3 -0
  81. data/spec/suites/rspec_2/support/matchers/wildcard_matcher_matchers.rb +32 -0
  82. data/spec/suites/rspec_2/support/mixins/double_definition_creator_helpers.rb +173 -0
  83. data/spec/suites/rspec_2/support/mixins/mock_definition_creator_helpers.rb +45 -0
  84. data/spec/suites/rspec_2/support/mixins/proxy_definition_creator_helpers.rb +33 -0
  85. data/spec/suites/rspec_2/support/mixins/stub_creator_helpers.rb +43 -0
  86. data/spec/suites/rspec_2/support/mixins/stub_definition_creator_helpers.rb +45 -0
  87. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/argument_expectations_with_never_called_qualifier.rb +39 -0
  88. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/argument_expectations_with_times_called_qualifier.rb +50 -0
  89. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/argument_expectations_without_qualifiers.rb +131 -0
  90. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/dont_allow.rb +148 -0
  91. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/mock_instance_of.rb +26 -0
  92. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/mock_instance_of_strong.rb +28 -0
  93. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/mock_proxy.rb +11 -0
  94. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/mock_strong.rb +37 -0
  95. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/mocking.rb +107 -0
  96. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/stub_instance_of.rb +32 -0
  97. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/stub_instance_of_strong.rb +39 -0
  98. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/stub_proxy.rb +11 -0
  99. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/stub_strong.rb +37 -0
  100. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/stubbing.rb +57 -0
  101. data/spec/suites/rspec_2/support/shared_examples/double_definition_creators/array_flatten_bug.rb +35 -0
  102. data/spec/suites/rspec_2/support/shared_examples/double_definition_creators/block_form.rb +31 -0
  103. data/spec/suites/rspec_2/support/shared_examples/double_definition_creators/comparing_arity.rb +63 -0
  104. data/spec/suites/rspec_2/support/shared_examples/double_definition_creators/object_is_proxy.rb +43 -0
  105. data/spec/suites/rspec_2/support/shared_examples/double_definition_creators/sequential_invocations.rb +26 -0
  106. data/spec/suites/rspec_2/support/shared_examples/double_definition_creators/setting_implementation.rb +51 -0
  107. data/spec/suites/rspec_2/support/shared_examples/double_definition_creators/yields.rb +81 -0
  108. data/spec/suites/rspec_2/support/shared_examples/space.rb +13 -0
  109. data/spec/suites/rspec_2/support/shared_examples/times_called_expectation.rb +9 -0
  110. data/spec/suites/rspec_2/unit/core_ext/array_spec.rb +39 -0
  111. data/spec/suites/rspec_2/unit/core_ext/enumerable_spec.rb +53 -0
  112. data/spec/suites/rspec_2/unit/core_ext/hash_spec.rb +55 -0
  113. data/spec/suites/rspec_2/unit/core_ext/range_spec.rb +41 -0
  114. data/spec/suites/rspec_2/unit/core_ext/regexp_spec.rb +41 -0
  115. data/spec/suites/rspec_2/unit/deprecations_spec.rb +27 -0
  116. data/spec/suites/rspec_2/unit/double_definitions/child_double_definition_create_spec.rb +114 -0
  117. data/spec/suites/rspec_2/unit/double_definitions/double_definition_create_blank_slate_spec.rb +93 -0
  118. data/spec/suites/rspec_2/unit/double_definitions/double_definition_create_spec.rb +446 -0
  119. data/spec/suites/rspec_2/unit/dsl/double_creators_spec.rb +133 -0
  120. data/spec/suites/rspec_2/unit/dsl/space_spec.rb +99 -0
  121. data/spec/suites/rspec_2/unit/dsl/wildcard_matchers_spec.rb +67 -0
  122. data/spec/suites/rspec_2/unit/errors/rr_error_spec.rb +67 -0
  123. data/spec/suites/rspec_2/unit/expectations/any_argument_expectation_spec.rb +48 -0
  124. data/spec/suites/rspec_2/unit/expectations/anything_argument_equality_expectation_spec.rb +14 -0
  125. data/spec/suites/rspec_2/unit/expectations/argument_equality_expectation_spec.rb +135 -0
  126. data/spec/suites/rspec_2/unit/expectations/boolean_argument_equality_expectation_spec.rb +30 -0
  127. data/spec/suites/rspec_2/unit/expectations/hash_including_argument_equality_expectation_spec.rb +92 -0
  128. data/spec/suites/rspec_2/unit/expectations/satisfy_argument_equality_expectation_spec.rb +61 -0
  129. data/spec/suites/rspec_2/unit/expectations/times_called_expectation/any_times_matcher_spec.rb +22 -0
  130. data/spec/suites/rspec_2/unit/expectations/times_called_expectation/at_least_matcher_spec.rb +37 -0
  131. data/spec/suites/rspec_2/unit/expectations/times_called_expectation/at_most_matcher_spec.rb +43 -0
  132. data/spec/suites/rspec_2/unit/expectations/times_called_expectation/integer_matcher_spec.rb +58 -0
  133. data/spec/suites/rspec_2/unit/expectations/times_called_expectation/proc_matcher_spec.rb +35 -0
  134. data/spec/suites/rspec_2/unit/expectations/times_called_expectation/range_matcher_spec.rb +39 -0
  135. data/spec/suites/rspec_2/unit/hash_with_object_id_key_spec.rb +88 -0
  136. data/spec/suites/rspec_2/unit/injections/double_injection/double_injection_spec.rb +533 -0
  137. data/spec/suites/rspec_2/unit/injections/double_injection/double_injection_verify_spec.rb +32 -0
  138. data/spec/suites/rspec_2/unit/integrations/rspec/invocation_matcher_spec.rb +297 -0
  139. data/spec/suites/rspec_2/unit/integrations/rspec_spec.rb +70 -0
  140. data/spec/suites/rspec_2/unit/rr_spec.rb +28 -0
  141. data/spec/suites/rspec_2/unit/space_spec.rb +598 -0
  142. data/spec/suites/rspec_2/unit/spy_verification_spec.rb +133 -0
  143. data/spec/suites/rspec_2/unit/times_called_matchers/any_times_matcher_spec.rb +46 -0
  144. data/spec/suites/rspec_2/unit/times_called_matchers/at_least_matcher_spec.rb +54 -0
  145. data/spec/suites/rspec_2/unit/times_called_matchers/at_most_matcher_spec.rb +69 -0
  146. data/spec/suites/rspec_2/unit/times_called_matchers/integer_matcher_spec.rb +69 -0
  147. data/spec/suites/rspec_2/unit/times_called_matchers/proc_matcher_spec.rb +54 -0
  148. data/spec/suites/rspec_2/unit/times_called_matchers/range_matcher_spec.rb +75 -0
  149. data/spec/suites/rspec_2/unit/times_called_matchers/times_called_matcher_spec.rb +117 -0
  150. data/spec/suites/rspec_2/unit/wildcard_matchers/anything_spec.rb +33 -0
  151. data/spec/suites/rspec_2/unit/wildcard_matchers/boolean_spec.rb +45 -0
  152. data/spec/suites/rspec_2/unit/wildcard_matchers/duck_type_spec.rb +64 -0
  153. data/spec/suites/rspec_2/unit/wildcard_matchers/hash_including_spec.rb +64 -0
  154. data/spec/suites/rspec_2/unit/wildcard_matchers/is_a_spec.rb +55 -0
  155. data/spec/suites/rspec_2/unit/wildcard_matchers/numeric_spec.rb +46 -0
  156. data/spec/suites/rspec_2/unit/wildcard_matchers/satisfy_spec.rb +57 -0
  157. data/spec/support/adapter.rb +22 -0
  158. data/spec/support/adapter_tests/base.rb +45 -0
  159. data/spec/support/adapter_tests/minitest.rb +7 -0
  160. data/spec/support/adapter_tests/rspec.rb +70 -0
  161. data/spec/support/adapter_tests/test_unit.rb +47 -0
  162. data/spec/support/command_runner.rb +105 -0
  163. data/spec/support/generator.rb +56 -0
  164. data/spec/support/integration_tests/base.rb +64 -0
  165. data/spec/support/integration_tests/rails.rb +60 -0
  166. data/spec/support/integration_tests/rails_minitest.rb +13 -0
  167. data/spec/support/integration_tests/rails_rspec.rb +13 -0
  168. data/spec/support/integration_tests/rails_test_unit.rb +13 -0
  169. data/spec/support/integration_tests/rails_test_unit_like.rb +13 -0
  170. data/spec/support/integration_tests/ruby.rb +7 -0
  171. data/spec/support/integration_tests/ruby_minitest.rb +13 -0
  172. data/spec/support/integration_tests/ruby_rspec.rb +13 -0
  173. data/spec/support/integration_tests/ruby_test_unit.rb +13 -0
  174. data/spec/support/matchers/be_a_subset_of_matcher.rb +24 -0
  175. data/spec/support/project/cucumber.rb +50 -0
  176. data/spec/support/project/generator.rb +348 -0
  177. data/spec/support/project/minitest.rb +39 -0
  178. data/spec/support/project/rails.rb +199 -0
  179. data/spec/support/project/rails_minitest.rb +17 -0
  180. data/spec/support/project/rails_rspec.rb +50 -0
  181. data/spec/support/project/rails_test_unit.rb +17 -0
  182. data/spec/support/project/rails_test_unit_like.rb +17 -0
  183. data/spec/support/project/rspec.rb +69 -0
  184. data/spec/support/project/ruby.rb +34 -0
  185. data/spec/support/project/ruby_minitest.rb +11 -0
  186. data/spec/support/project/ruby_rspec.rb +29 -0
  187. data/spec/support/project/ruby_test_unit.rb +11 -0
  188. data/spec/support/project/ruby_test_unit_like.rb +21 -0
  189. data/spec/support/project/test_unit.rb +29 -0
  190. data/spec/support/project/test_unit_like.rb +7 -0
  191. data/spec/support/project/tests_runner.rb +22 -0
  192. data/spec/support/test.sqlite3 +0 -0
  193. data/spec/support/test_case/generator.rb +53 -0
  194. data/spec/support/test_case/minitest.rb +13 -0
  195. data/spec/support/test_case/rspec.rb +19 -0
  196. data/spec/support/test_case/test_unit.rb +21 -0
  197. data/spec/support/test_file/generator.rb +120 -0
  198. data/spec/support/test_file/minitest.rb +19 -0
  199. data/spec/support/test_file/rails_minitest.rb +7 -0
  200. data/spec/support/test_file/rails_rspec.rb +12 -0
  201. data/spec/support/test_file/rails_test_unit.rb +25 -0
  202. data/spec/support/test_file/rspec.rb +33 -0
  203. data/spec/support/test_file/test_unit.rb +36 -0
  204. data/spec/support/test_helper/generator.rb +27 -0
  205. data/spec/support/test_helper/minitest.rb +7 -0
  206. data/spec/support/test_helper/rails.rb +31 -0
  207. data/spec/support/test_helper/rails_minitest.rb +7 -0
  208. data/spec/support/test_helper/rails_rspec.rb +25 -0
  209. data/spec/support/test_helper/rails_test_unit.rb +23 -0
  210. data/spec/support/test_helper/rspec.rb +7 -0
  211. data/spec/support/test_helper/ruby.rb +31 -0
  212. data/spec/support/test_helper/test_unit.rb +7 -0
  213. metadata +240 -19
  214. data/VERSION +0 -1
  215. data/lib/rr/adapters.rb +0 -44
  216. data/lib/rr/adapters/rr_methods.rb +0 -142
  217. data/lib/rr/integrations/rspec_1.rb +0 -46
  218. data/lib/rr/integrations/test_unit_1.rb +0 -63
  219. data/lib/rr/integrations/test_unit_2.rb +0 -15
  220. data/lib/rr/integrations/test_unit_200.rb +0 -27
  221. data/lib/rr/integrations/test_unit_200_active_support.rb +0 -25
  222. data/lib/rr/integrations/test_unit_2_active_support.rb +0 -38
  223. data/lib/rr/proc_from_block.rb +0 -11
@@ -30,11 +30,11 @@ module RR
30
30
  @double_injection_strategy = self.class.default_double_injection_strategy.call(self)
31
31
  end
32
32
 
33
- def call(method_name, *args, &handler)
33
+ def call(method_name, args, kwargs, &handler)
34
34
  definition = DoubleDefinition.new(self)
35
- verification_strategy.call(definition, method_name, args, handler)
36
- implementation_strategy.call(definition, method_name, args, handler)
37
- double_injection_strategy.call(definition, method_name, args, handler)
35
+ verification_strategy.call(definition, method_name, args, kwargs, handler)
36
+ implementation_strategy.call(definition, method_name, args, kwargs, handler)
37
+ double_injection_strategy.call(definition, method_name, args, kwargs, handler)
38
38
  definition
39
39
  end
40
40
 
@@ -81,7 +81,7 @@ module RR
81
81
  self
82
82
  elsif method_name
83
83
  # TODO: Pass in arguments.
84
- call(method_name)
84
+ call(method_name, [], {})
85
85
  else
86
86
  DoubleDefinitionCreateBlankSlate.new(self, &definition_eval_block)
87
87
  end
@@ -14,13 +14,19 @@ module RR
14
14
  end
15
15
  end
16
16
 
17
- def method_missing(method_name, *args, &block)
18
- @double_definition_create.call(method_name, *args, &block)
17
+ if KeywordArguments.fully_supported?
18
+ def method_missing(method_name, *args, **kwargs, &block)
19
+ @double_definition_create.call(method_name, args, kwargs, &block)
20
+ end
21
+ else
22
+ def method_missing(method_name, *args, &block)
23
+ @double_definition_create.call(method_name, args, {}, &block)
24
+ end
19
25
  end
20
26
 
21
27
  def __double_definition_create__
22
28
  @double_definition_create
23
29
  end
24
- end
30
+ end
25
31
  end
26
- end
32
+ end
@@ -3,7 +3,7 @@ module RR
3
3
  module DoubleInjections
4
4
  class AnyInstanceOf
5
5
  extend(Module.new do
6
- include RR::Adapters::RRMethods
6
+ include RR::DSL
7
7
 
8
8
  def call(subject_class, stubbed_methods=nil, &block)
9
9
  strategy_lambda = lambda do |double_definition_create|
@@ -3,7 +3,7 @@ module RR
3
3
  module DoubleInjections
4
4
  class Instance
5
5
  extend(Module.new do
6
- include ::RR::Adapters::RRMethods
6
+ include ::RR::DSL
7
7
 
8
8
  def call(double_method_name, *args, &definition_eval_block)
9
9
  double_definition_create = DoubleDefinitions::DoubleDefinitionCreate.new
@@ -13,4 +13,4 @@ module RR
13
13
  end
14
14
  end
15
15
  end
16
- end
16
+ end
@@ -2,7 +2,12 @@ module RR
2
2
  module DoubleDefinitions
3
3
  module Strategies
4
4
  class Strategy
5
- attr_reader :double_definition_create, :definition, :method_name, :args, :handler
5
+ attr_reader :double_definition_create
6
+ attr_reader :definition
7
+ attr_reader :method_name
8
+ attr_reader :args
9
+ attr_reader :kwargs
10
+ attr_reader :handler
6
11
 
7
12
  include Space::Reader
8
13
 
@@ -10,8 +15,12 @@ module RR
10
15
  @double_definition_create = double_definition_create
11
16
  end
12
17
 
13
- def call(definition, method_name, args, handler)
14
- @definition, @method_name, @args, @handler = definition, method_name, args, handler
18
+ def call(definition, method_name, args, kwargs, handler)
19
+ @definition = definition
20
+ @method_name = method_name
21
+ @args = args
22
+ @kwargs = kwargs
23
+ @handler = handler
15
24
  do_call
16
25
  end
17
26
 
@@ -23,11 +32,21 @@ module RR
23
32
  raise NotImplementedError
24
33
  end
25
34
 
26
- def permissive_argument
27
- if args.empty?
28
- definition.with_any_args
29
- else
30
- definition.with(*args)
35
+ if KeywordArguments.fully_supported?
36
+ def permissive_argument
37
+ if args.empty? and kwargs.empty?
38
+ definition.with_any_args
39
+ else
40
+ definition.with(*args, **kwargs)
41
+ end
42
+ end
43
+ else
44
+ def permissive_argument
45
+ if args.empty?
46
+ definition.with_any_args
47
+ else
48
+ definition.with(*args)
49
+ end
31
50
  end
32
51
  end
33
52
 
@@ -32,8 +32,14 @@ module RR
32
32
  # end
33
33
  class Mock < VerificationStrategy
34
34
  protected
35
- def do_call
36
- definition.with(*args).once
35
+ if KeywordArguments.fully_supported?
36
+ def do_call
37
+ definition.with(*args, **kwargs).once
38
+ end
39
+ else
40
+ def do_call
41
+ definition.with(*args).once
42
+ end
37
43
  end
38
44
  end
39
45
  end
@@ -15,9 +15,10 @@ module RR
15
15
  @wildcard_non_terminal_doubles_to_attempt = []
16
16
  end
17
17
 
18
- def find_all_matches(args)
18
+ def find_all_matches(args, kwargs)
19
+ kwargs ||= {}
19
20
  @doubles.each do |double|
20
- if double.exact_match?(*args)
21
+ if double.exact_match?(args, kwargs)
21
22
  matching_doubles << double
22
23
  if double.attempt?
23
24
  if double.terminal?
@@ -26,7 +27,7 @@ module RR
26
27
  exact_non_terminal_doubles_to_attempt << double
27
28
  end
28
29
  end
29
- elsif double.wildcard_match?(*args)
30
+ elsif double.wildcard_match?(args, kwargs)
30
31
  matching_doubles << double
31
32
  if double.attempt?
32
33
  if double.terminal?
data/lib/rr/dsl.rb ADDED
@@ -0,0 +1,152 @@
1
+ module RR
2
+ module DSL
3
+ METHODS_TO_EXCLUDE_FROM_SPYING = [
4
+ :methods,
5
+ :==,
6
+ :__send__,
7
+ :__id__,
8
+ :object_id,
9
+ :class,
10
+ :respond_to?,
11
+ :inspect,
12
+ :to_s,
13
+ :respond_to_missing?,
14
+ :instance_eval,
15
+ :instance_exec
16
+ ]
17
+
18
+ include DoubleDefinitions::Strategies::StrategyMethods
19
+
20
+ def mock(subject=DoubleDefinitions::DoubleDefinitionCreate::NO_SUBJECT, method_name=nil, &definition_eval_block)
21
+ double_definition_create = DoubleDefinitions::DoubleDefinitionCreate.new
22
+ double_definition_create.mock(subject, method_name, &definition_eval_block)
23
+ end
24
+
25
+ def stub(subject=DoubleDefinitions::DoubleDefinitionCreate::NO_SUBJECT, method_name=nil, &definition_eval_block)
26
+ double_definition_create = DoubleDefinitions::DoubleDefinitionCreate.new
27
+ double_definition_create.stub(subject, method_name, &definition_eval_block)
28
+ end
29
+
30
+ def dont_allow(subject=DoubleDefinitions::DoubleDefinitionCreate::NO_SUBJECT, method_name=nil, &definition_eval_block)
31
+ double_definition_create = DoubleDefinitions::DoubleDefinitionCreate.new
32
+ double_definition_create.dont_allow(subject, method_name, &definition_eval_block)
33
+ end
34
+
35
+ def proxy(subject=DoubleDefinitions::DoubleDefinitionCreate::NO_SUBJECT, method_name=nil, &definition_eval_block)
36
+ double_definition_create = DoubleDefinitions::DoubleDefinitionCreate.new
37
+ double_definition_create.proxy(subject, method_name, &definition_eval_block)
38
+ end
39
+
40
+ def strong(subject=DoubleDefinitions::DoubleDefinitionCreate::NO_SUBJECT, method_name=nil, &definition_eval_block)
41
+ double_definition_create = DoubleDefinitions::DoubleDefinitionCreate.new
42
+ double_definition_create.strong(subject, method_name, &definition_eval_block)
43
+ end
44
+
45
+ def instance_of(subject=DoubleDefinitions::DoubleDefinitionCreate::NO_SUBJECT, method_name=nil, &definition_eval_block)
46
+ double_definition_create = DoubleDefinitions::DoubleDefinitionCreate.new
47
+ double_definition_create.instance_of(subject, method_name, &definition_eval_block)
48
+ end
49
+
50
+ def any_instance_of(*args, &block)
51
+ RR::DoubleDefinitions::DoubleInjections::AnyInstanceOf.call(*args, &block)
52
+ end
53
+
54
+ # Verifies all the DoubleInjection objects have met their
55
+ # TimesCalledExpectations.
56
+ def verify
57
+ RR::Space.instance.verify_doubles
58
+ end
59
+
60
+ # Resets the registered Doubles and ordered Doubles
61
+ def reset
62
+ RR::Space.instance.reset
63
+ end
64
+
65
+ # Returns a AnyTimesMatcher. This is meant to be passed in as an argument
66
+ # to Double#times.
67
+ #
68
+ # mock(object).method_name(anything).times(any_times) {return_value}
69
+ def any_times
70
+ TimesCalledMatchers::AnyTimesMatcher.new
71
+ end
72
+
73
+ # Sets up an Anything wildcard ArgumentEqualityExpectation
74
+ # that succeeds when passed any argument.
75
+ # mock(object).method_name(anything) {return_value}
76
+ # object.method_name("an arbitrary value") # passes
77
+ def anything
78
+ RR::WildcardMatchers::Anything.new
79
+ end
80
+
81
+ # Sets up an IsA wildcard ArgumentEqualityExpectation
82
+ # that succeeds when passed an argument of a certain type.
83
+ # mock(object).method_name(is_a(String)) {return_value}
84
+ # object.method_name("A String") # passes
85
+ def is_a(klass)
86
+ RR::WildcardMatchers::IsA.new(klass)
87
+ end
88
+
89
+ # Sets up an Numeric wildcard ArgumentEqualityExpectation
90
+ # that succeeds when passed an argument that is ::Numeric.
91
+ # mock(object).method_name(numeric) {return_value}
92
+ # object.method_name(99) # passes
93
+ def numeric
94
+ RR::WildcardMatchers::Numeric.new
95
+ end
96
+
97
+ # Sets up an Boolean wildcard ArgumentEqualityExpectation
98
+ # that succeeds when passed an argument that is a ::Boolean.
99
+ # mock(object).method_name(boolean) {return_value}
100
+ # object.method_name(false) # passes
101
+ def boolean
102
+ RR::WildcardMatchers::Boolean.new
103
+ end
104
+
105
+ # Sets up a DuckType wildcard ArgumentEqualityExpectation
106
+ # that succeeds when the passed argument implements the methods.
107
+ # arg = Object.new
108
+ # def arg.foo; end
109
+ # def arg.bar; end
110
+ # mock(object).method_name(duck_type(:foo, :bar)) {return_value}
111
+ # object.method_name(arg) # passes
112
+ def duck_type(*args)
113
+ RR::WildcardMatchers::DuckType.new(*args)
114
+ end
115
+
116
+ # Sets up a HashIncluding wildcard ArgumentEqualityExpectation
117
+ # that succeeds when the passed argument contains at least those keys
118
+ # and values of the expectation.
119
+ # mock(object).method_name(hash_including(:foo => 1)) {return_value}
120
+ # object.method_name({:foo => 1, :bar => 2) # passes
121
+ def hash_including(expected_hash)
122
+ RR::WildcardMatchers::HashIncluding.new(expected_hash)
123
+ end
124
+
125
+ # Sets up a Satisfy wildcard ArgumentEqualityExpectation
126
+ # that succeeds when the passed argument causes the expectation's
127
+ # proc to return true.
128
+ # mock(object).method_name(satisfy {|arg| arg == :foo}) {return_value}
129
+ # object.method_name(:foo) # passes
130
+ def satisfy(expectation_proc=nil, &block)
131
+ expectation_proc ||= block
132
+ RR::WildcardMatchers::Satisfy.new(expectation_proc)
133
+ end
134
+
135
+ def spy(subject)
136
+ subject_methods = subject.public_methods.map {|method_name| method_name.to_sym }
137
+ methods_to_stub = subject_methods - METHODS_TO_EXCLUDE_FROM_SPYING
138
+
139
+ methods_to_stub.each do |method|
140
+ stub.proxy(subject, method)
141
+ end
142
+ end
143
+
144
+ def received(subject)
145
+ RR::SpyVerificationProxy.new(subject)
146
+ end
147
+
148
+ instance_methods.each do |name|
149
+ alias_method "rr_#{name}", name
150
+ end
151
+ end
152
+ end
@@ -2,14 +2,14 @@ module RR
2
2
  module Expectations
3
3
  class AnyArgumentExpectation < ArgumentEqualityExpectation #:nodoc:
4
4
  def initialize
5
- super
5
+ super([], {})
6
6
  end
7
7
 
8
- def exact_match?(*arguments)
8
+ def exact_match?(arguments, keyword_arguments)
9
9
  false
10
10
  end
11
11
 
12
- def wildcard_match?(*arguments)
12
+ def wildcard_match?(arguments, keyword_arguments)
13
13
  true
14
14
  end
15
15
 
@@ -18,4 +18,4 @@ module RR
18
18
  end
19
19
  end
20
20
  end
21
- end
21
+ end
@@ -10,20 +10,37 @@ module RR
10
10
  end
11
11
 
12
12
  attr_reader :expected_arguments
13
+ attr_reader :expected_keyword_arguments
13
14
 
14
- def initialize(*expected_arguments)
15
+ def initialize(expected_arguments,
16
+ expected_keyword_arguments)
15
17
  @expected_arguments = expected_arguments
18
+ @expected_keyword_arguments = expected_keyword_arguments
16
19
  end
17
20
 
18
- def exact_match?(*arguments)
21
+ def exact_match?(arguments, keyword_arguments)
19
22
  return false unless arguments.length == expected_arguments.length
20
23
  arguments.each_with_index do |arg, index|
21
- return false unless self.class.recursive_safe_eq(expected_arguments[index], arg)
24
+ expected_arg = expected_arguments[index]
25
+ return false unless self.class.recursive_safe_eq(expected_arg, arg)
26
+ end
27
+ keywords = keyword_arguments.keys
28
+ expected_keywords = expected_keyword_arguments.keys
29
+ unless keywords.length == expected_keywords.length
30
+ return false
31
+ end
32
+ keywords.each do |keyword|
33
+ keyword_argument = keyword_arguments[keyword]
34
+ expected_keyword_argument = expected_keyword_arguments[keyword]
35
+ unless self.class.recursive_safe_eq(expected_keyword_argument,
36
+ keyword_argument)
37
+ return false
38
+ end
22
39
  end
23
40
  true
24
41
  end
25
42
 
26
- def wildcard_match?(*arguments)
43
+ def wildcard_match?(arguments, keyword_arguments)
27
44
  return false unless arguments.length == expected_arguments.length
28
45
  arguments.each_with_index do |arg, index|
29
46
  expected_argument = expected_arguments[index]
@@ -33,11 +50,32 @@ module RR
33
50
  return false unless self.class.recursive_safe_eq(expected_argument, arg)
34
51
  end
35
52
  end
53
+ keywords = keyword_arguments.keys
54
+ expected_keywords = expected_keyword_arguments.keys
55
+ unless keywords.length == expected_keywords.length
56
+ return false
57
+ end
58
+ keywords.each do |keyword|
59
+ keyword_argument = keyword_arguments[keyword]
60
+ expected_keyword_argument = expected_keyword_arguments[keyword]
61
+ if expected_keyword_argument.respond_to?(:wildcard_match?)
62
+ unless expected_keyword_argument.wildcard_match?(keyword_argument)
63
+ return false
64
+ end
65
+ else
66
+ unless self.class.recursive_safe_eq(expected_keyword_argument,
67
+ keyword_argument)
68
+ return false
69
+ end
70
+ end
71
+ end
36
72
  true
37
73
  end
38
74
 
39
75
  def ==(other)
40
- expected_arguments == other.expected_arguments
76
+ other.is_a?(self.class) and
77
+ expected_arguments == other.expected_arguments and
78
+ expected_keyword_arguments == other.expected_keyword_arguments
41
79
  end
42
80
  end
43
81
  end
@@ -31,15 +31,20 @@ module RR
31
31
  exists?((class << subject; self; end), method_name)
32
32
  end
33
33
 
34
- def dispatch_method(subject, subject_class, method_name, arguments, block)
34
+ def dispatch_method(subject,
35
+ subject_class,
36
+ method_name,
37
+ arguments,
38
+ keyword_arguments,
39
+ block)
35
40
  subject_eigenclass = (class << subject; self; end)
36
41
  if (
37
42
  exists?(subject_class, method_name) &&
38
- (subject_class == subject_eigenclass) || !subject.is_a?(Class)
43
+ ((subject_class == subject_eigenclass) || !subject.is_a?(Class))
39
44
  )
40
- find(subject_class, method_name.to_sym).dispatch_method(subject, arguments, block)
45
+ find(subject_class, method_name.to_sym).dispatch_method(subject, arguments, keyword_arguments, block)
41
46
  else
42
- new(subject_class, method_name.to_sym).dispatch_original_method(subject, arguments, block)
47
+ new(subject_class, method_name.to_sym).dispatch_original_method(subject, arguments, keyword_arguments, block)
43
48
  end
44
49
  end
45
50
 
@@ -91,7 +96,9 @@ module RR
91
96
 
92
97
  attr_reader :subject_class, :method_name, :doubles
93
98
 
94
- MethodArguments = Struct.new(:arguments, :block)
99
+ MethodArguments = Struct.new(:arguments,
100
+ :keyword_arguments,
101
+ :block)
95
102
 
96
103
  def initialize(subject_class, method_name)
97
104
  @subject_class = subject_class
@@ -111,7 +118,11 @@ module RR
111
118
  # is called.
112
119
  def bind
113
120
  if subject_has_method_defined?(method_name)
114
- bind_method_with_alias
121
+ if subject_has_original_method?
122
+ bind_method
123
+ else
124
+ bind_method_with_alias
125
+ end
115
126
  else
116
127
  Injections::MethodMissingInjection.find_or_create(subject_class)
117
128
  Injections::SingletonMethodAddedInjection.find_or_create(subject_class)
@@ -141,13 +152,37 @@ module RR
141
152
  id = BoundObjects.size
142
153
  BoundObjects[id] = subject_class
143
154
 
144
- subject_class.class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
145
- def #{method_name}(*args, &block)
146
- arguments = MethodArguments.new(args, block)
147
- obj = ::RR::Injections::DoubleInjection::BoundObjects[#{id}]
148
- ::RR::Injections::DoubleInjection.dispatch_method(self, obj, :#{method_name}, arguments.arguments, arguments.block)
149
- end
150
- RUBY
155
+ if KeywordArguments.fully_supported?
156
+ subject_class.class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
157
+ def #{method_name}(*args, **kwargs, &block)
158
+ arguments = MethodArguments.new(args, kwargs, block)
159
+ obj = ::RR::Injections::DoubleInjection::BoundObjects[#{id}]
160
+ ::RR::Injections::DoubleInjection.dispatch_method(
161
+ self,
162
+ obj,
163
+ :#{method_name},
164
+ arguments.arguments,
165
+ arguments.keyword_arguments,
166
+ arguments.block
167
+ )
168
+ end
169
+ RUBY
170
+ else
171
+ subject_class.class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
172
+ def #{method_name}(*args, &block)
173
+ arguments = MethodArguments.new(args, {}, block)
174
+ obj = ::RR::Injections::DoubleInjection::BoundObjects[#{id}]
175
+ ::RR::Injections::DoubleInjection.dispatch_method(
176
+ self,
177
+ obj,
178
+ :#{method_name},
179
+ arguments.arguments,
180
+ arguments.keyword_arguments,
181
+ arguments.block
182
+ )
183
+ end
184
+ RUBY
185
+ end
151
186
  self
152
187
  end
153
188
 
@@ -175,17 +210,29 @@ module RR
175
210
  end
176
211
  end
177
212
 
178
- def dispatch_method(subject, args, block)
213
+ def dispatch_method(subject, args, kwargs, block)
179
214
  if @dispatch_method_delegates_to_dispatch_original_method
180
- dispatch_original_method(subject, args, block)
215
+ dispatch_original_method(subject, args, kwargs, block)
181
216
  else
182
- dispatch = MethodDispatches::MethodDispatch.new(self, subject, args, block)
217
+ dispatch = MethodDispatches::MethodDispatch.new(
218
+ self,
219
+ subject,
220
+ args,
221
+ kwargs,
222
+ block
223
+ )
183
224
  dispatch.call
184
225
  end
185
226
  end
186
227
 
187
- def dispatch_original_method(subject, args, block)
188
- dispatch = MethodDispatches::MethodDispatch.new(self, subject, args, block)
228
+ def dispatch_original_method(subject, args, kwargs, block)
229
+ dispatch = MethodDispatches::MethodDispatch.new(
230
+ self,
231
+ subject,
232
+ args,
233
+ kwargs,
234
+ block
235
+ )
189
236
  dispatch.call_original_method
190
237
  end
191
238
 
@@ -206,7 +253,8 @@ module RR
206
253
 
207
254
  protected
208
255
  def deferred_bind_method
209
- unless subject_has_method_defined?(original_method_alias_name)
256
+ if respond_to?(method_name) and
257
+ not subject_has_method_defined?(original_method_alias_name)
210
258
  bind_method_with_alias
211
259
  end
212
260
  @performed_deferred_bind = true