rr 1.1.2 → 3.0.2

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 (157) hide show
  1. checksums.yaml +5 -5
  2. data/Appraisals +3 -43
  3. data/CHANGES.md +93 -0
  4. data/CREDITS.md +5 -0
  5. data/Gemfile +1 -17
  6. data/README.md +29 -32
  7. data/Rakefile +42 -40
  8. data/doc/02_syntax_comparison.md +1 -0
  9. data/lib/rr/class_instance_method_defined.rb +1 -1
  10. data/lib/rr/core_ext/array.rb +2 -0
  11. data/lib/rr/core_ext/hash.rb +2 -0
  12. data/lib/rr/deprecations.rb +97 -0
  13. data/lib/rr/double.rb +28 -10
  14. data/lib/rr/double_definitions/double_definition.rb +39 -16
  15. data/lib/rr/double_definitions/double_definition_create.rb +5 -5
  16. data/lib/rr/double_definitions/double_definition_create_blank_slate.rb +10 -4
  17. data/lib/rr/double_definitions/double_injections/any_instance_of.rb +1 -1
  18. data/lib/rr/double_definitions/double_injections/instance.rb +2 -2
  19. data/lib/rr/double_definitions/strategies/strategy.rb +27 -8
  20. data/lib/rr/double_definitions/strategies/verification/mock.rb +8 -2
  21. data/lib/rr/double_matches.rb +4 -3
  22. data/lib/rr/dsl.rb +152 -0
  23. data/lib/rr/expectations/any_argument_expectation.rb +4 -4
  24. data/lib/rr/expectations/argument_equality_expectation.rb +43 -5
  25. data/lib/rr/injections/double_injection.rb +85 -26
  26. data/lib/rr/injections/method_missing_injection.rb +37 -6
  27. data/lib/rr/integrations/minitest_4.rb +1 -1
  28. data/lib/rr/integrations/minitest_4_active_support.rb +1 -1
  29. data/lib/rr/integrations/rspec/invocation_matcher.rb +0 -8
  30. data/lib/rr/integrations/rspec_2.rb +20 -2
  31. data/lib/rr/keyword_arguments.rb +15 -0
  32. data/lib/rr/method_dispatches/base_method_dispatch.rb +22 -5
  33. data/lib/rr/method_dispatches/method_dispatch.rb +21 -10
  34. data/lib/rr/method_dispatches/method_missing_dispatch.rb +14 -5
  35. data/lib/rr/recorded_call.rb +35 -0
  36. data/lib/rr/recorded_calls.rb +23 -9
  37. data/lib/rr/space.rb +15 -5
  38. data/lib/rr/spy_verification.rb +13 -5
  39. data/lib/rr/version.rb +1 -1
  40. data/lib/rr/wildcard_matchers.rb +10 -10
  41. data/lib/rr/without_autohook.rb +7 -14
  42. data/rr.gemspec +8 -3
  43. data/spec/defines_spec_suite_tasks.rb +12 -0
  44. data/spec/global_helper.rb +5 -0
  45. data/spec/spec_suite_configuration.rb +1 -7
  46. data/spec/suites.yml +0 -14
  47. data/spec/suites/rspec_2/functional/any_instance_of_spec.rb +133 -33
  48. data/spec/suites/rspec_2/functional/dont_allow_spec.rb +13 -8
  49. data/spec/suites/rspec_2/functional/mock_bang_spec.rb +20 -0
  50. data/spec/suites/rspec_2/functional/mock_instance_of_spec.rb +14 -0
  51. data/spec/suites/rspec_2/functional/mock_instance_of_strong_spec.rb +15 -0
  52. data/spec/suites/rspec_2/functional/mock_proxy_instance_of_spec.rb +15 -0
  53. data/spec/suites/rspec_2/functional/mock_proxy_spec.rb +14 -0
  54. data/spec/suites/rspec_2/functional/mock_spec.rb +8 -232
  55. data/spec/suites/rspec_2/functional/mock_strong_spec.rb +14 -0
  56. data/spec/suites/rspec_2/functional/received_spec.rb +16 -0
  57. data/spec/suites/rspec_2/functional/spy_spec.rb +89 -28
  58. data/spec/suites/rspec_2/functional/stub_bang_spec.rb +20 -0
  59. data/spec/suites/rspec_2/functional/stub_instance_of_spec.rb +15 -0
  60. data/spec/suites/rspec_2/functional/stub_instance_of_strong_spec.rb +15 -0
  61. data/spec/suites/rspec_2/functional/stub_proxy_instance_of_spec.rb +16 -0
  62. data/spec/suites/rspec_2/functional/stub_proxy_spec.rb +45 -0
  63. data/spec/suites/rspec_2/functional/stub_spec.rb +42 -161
  64. data/spec/suites/rspec_2/functional/stub_strong_spec.rb +15 -0
  65. data/spec/suites/rspec_2/helper.rb +2 -2
  66. data/spec/suites/rspec_2/support/mixins/double_definition_creator_helpers.rb +173 -0
  67. data/spec/suites/rspec_2/support/mixins/mock_definition_creator_helpers.rb +45 -0
  68. data/spec/suites/rspec_2/support/mixins/proxy_definition_creator_helpers.rb +33 -0
  69. data/spec/suites/rspec_2/support/mixins/stub_creator_helpers.rb +43 -0
  70. data/spec/suites/rspec_2/support/mixins/stub_definition_creator_helpers.rb +45 -0
  71. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/argument_expectations_with_never_called_qualifier.rb +39 -0
  72. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/argument_expectations_with_times_called_qualifier.rb +50 -0
  73. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/argument_expectations_without_qualifiers.rb +131 -0
  74. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/dont_allow.rb +148 -0
  75. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/mock_instance_of.rb +26 -0
  76. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/mock_instance_of_strong.rb +28 -0
  77. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/mock_proxy.rb +11 -0
  78. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/mock_strong.rb +37 -0
  79. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/mocking.rb +107 -0
  80. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/stub_instance_of.rb +32 -0
  81. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/stub_instance_of_strong.rb +39 -0
  82. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/stub_proxy.rb +11 -0
  83. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/stub_strong.rb +37 -0
  84. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/stubbing.rb +57 -0
  85. data/spec/suites/rspec_2/support/shared_examples/double_definition_creators/array_flatten_bug.rb +35 -0
  86. data/spec/suites/rspec_2/support/shared_examples/double_definition_creators/block_form.rb +31 -0
  87. data/spec/suites/rspec_2/support/shared_examples/double_definition_creators/comparing_arity.rb +63 -0
  88. data/spec/suites/rspec_2/support/shared_examples/double_definition_creators/object_is_proxy.rb +43 -0
  89. data/spec/suites/rspec_2/support/shared_examples/double_definition_creators/sequential_invocations.rb +26 -0
  90. data/spec/suites/rspec_2/support/shared_examples/double_definition_creators/setting_implementation.rb +51 -0
  91. data/spec/suites/rspec_2/support/shared_examples/double_definition_creators/yields.rb +81 -0
  92. data/spec/suites/rspec_2/unit/core_ext/enumerable_spec.rb +0 -28
  93. data/spec/suites/rspec_2/unit/deprecations_spec.rb +27 -0
  94. data/spec/suites/rspec_2/unit/double_definitions/double_definition_create_spec.rb +18 -18
  95. data/spec/suites/rspec_2/unit/dsl/double_creators_spec.rb +133 -0
  96. data/spec/suites/rspec_2/unit/dsl/space_spec.rb +99 -0
  97. data/spec/suites/rspec_2/unit/dsl/wildcard_matchers_spec.rb +67 -0
  98. data/spec/suites/rspec_2/unit/expectations/any_argument_expectation_spec.rb +9 -9
  99. data/spec/suites/rspec_2/unit/expectations/argument_equality_expectation_spec.rb +21 -21
  100. data/spec/suites/rspec_2/unit/expectations/boolean_argument_equality_expectation_spec.rb +4 -4
  101. data/spec/suites/rspec_2/unit/expectations/hash_including_argument_equality_expectation_spec.rb +31 -21
  102. data/spec/suites/rspec_2/unit/injections/double_injection/double_injection_spec.rb +0 -12
  103. data/spec/suites/rspec_2/unit/integrations/rspec_spec.rb +4 -19
  104. data/spec/suites/rspec_2/unit/space_spec.rb +7 -4
  105. data/spec/suites/rspec_2/unit/spy_verification_spec.rb +1 -1
  106. data/spec/support/adapter.rb +1 -1
  107. data/spec/support/adapter_tests/rspec.rb +19 -15
  108. data/spec/support/project/generator.rb +0 -4
  109. metadata +112 -57
  110. data/gemfiles/ruby_18_rspec_1.gemfile +0 -14
  111. data/gemfiles/ruby_18_rspec_1.gemfile.lock +0 -38
  112. data/gemfiles/ruby_18_rspec_1_rails_2.gemfile +0 -18
  113. data/gemfiles/ruby_18_rspec_1_rails_2.gemfile.lock +0 -64
  114. data/gemfiles/ruby_19_rspec_2_rails_3.gemfile +0 -15
  115. data/gemfiles/ruby_19_rspec_2_rails_3.gemfile.lock +0 -123
  116. data/lib/rr/adapters.rb +0 -34
  117. data/lib/rr/adapters/rr_methods.rb +0 -142
  118. data/lib/rr/integrations/rspec_1.rb +0 -46
  119. data/lib/rr/integrations/test_unit_1.rb +0 -63
  120. data/lib/rr/integrations/test_unit_2.rb +0 -17
  121. data/lib/rr/integrations/test_unit_200.rb +0 -27
  122. data/lib/rr/integrations/test_unit_200_active_support.rb +0 -25
  123. data/lib/rr/integrations/test_unit_2_active_support.rb +0 -38
  124. data/lib/rr/proc_from_block.rb +0 -11
  125. data/spec/suites/rspec_1/helper.rb +0 -24
  126. data/spec/suites/rspec_1/integration/rspec_1_spec.rb +0 -93
  127. data/spec/suites/rspec_1/integration/test_unit_1_spec.rb +0 -102
  128. data/spec/suites/rspec_1/integration/test_unit_2_spec.rb +0 -109
  129. data/spec/suites/rspec_1/spec_helper.rb +0 -3
  130. data/spec/suites/rspec_1_rails_2/integration/astc_rails_2_spec.rb +0 -141
  131. data/spec/suites/rspec_1_rails_2/integration/rspec_1_rails_2_spec.rb +0 -132
  132. data/spec/suites/rspec_1_rails_2/integration/test_unit_1_rails_2_spec.rb +0 -141
  133. data/spec/suites/rspec_1_rails_2/integration/test_unit_2_rails_2_spec.rb +0 -148
  134. data/spec/suites/rspec_1_rails_2/spec_helper.rb +0 -3
  135. data/spec/suites/rspec_2/functional/dsl_spec.rb +0 -13
  136. data/spec/suites/rspec_2/functional/instance_of_spec.rb +0 -14
  137. data/spec/suites/rspec_2/functional/proxy_spec.rb +0 -136
  138. data/spec/suites/rspec_2/functional/strong_spec.rb +0 -79
  139. data/spec/suites/rspec_2/integration/rspec_2_spec.rb +0 -133
  140. data/spec/suites/rspec_2/integration/test_unit_200_spec.rb +0 -102
  141. data/spec/suites/rspec_2/integration/test_unit_2_spec.rb +0 -109
  142. data/spec/suites/rspec_2/unit/adapters/rr_methods/double_creators_spec.rb +0 -135
  143. data/spec/suites/rspec_2/unit/adapters/rr_methods/space_spec.rb +0 -101
  144. data/spec/suites/rspec_2/unit/adapters/rr_methods/wildcard_matchers_spec.rb +0 -69
  145. data/spec/suites/rspec_2/unit/proc_from_block_spec.rb +0 -14
  146. data/spec/suites/rspec_2_rails_3/integration/astc_rails_3_spec.rb +0 -141
  147. data/spec/suites/rspec_2_rails_3/integration/minitest_4_rails_3_spec.rb +0 -148
  148. data/spec/suites/rspec_2_rails_3/integration/rspec_2_rails_3_spec.rb +0 -172
  149. data/spec/suites/rspec_2_rails_3/integration/test_unit_200_rails_3_spec.rb +0 -141
  150. data/spec/suites/rspec_2_rails_3/integration/test_unit_2_rails_3_spec.rb +0 -148
  151. data/spec/suites/rspec_2_rails_3/spec_helper.rb +0 -3
  152. data/spec/suites/rspec_2_rails_4/integration/astc_rails_4_spec.rb +0 -142
  153. data/spec/suites/rspec_2_rails_4/integration/minitest_4_rails_4_spec.rb +0 -149
  154. data/spec/suites/rspec_2_rails_4/integration/rspec_2_rails_4_spec.rb +0 -173
  155. data/spec/suites/rspec_2_rails_4/integration/test_unit_200_rails_4_spec.rb +0 -142
  156. data/spec/suites/rspec_2_rails_4/integration/test_unit_2_rails_4_spec.rb +0 -149
  157. data/spec/suites/rspec_2_rails_4/spec_helper.rb +0 -3
@@ -0,0 +1,32 @@
1
+ shared_context 'stub + instance_of' do
2
+ include StubDefinitionCreatorHelpers
3
+
4
+ context 'where subject is a class', method_type: :class do
5
+ context 'where methods being doubled already exist', methods_exist: true do
6
+ include_context 'tests for a double definition creator method that supports stubbing'
7
+
8
+ it "lets you stub methods which are called in #initialize" do
9
+ klass = Class.new do
10
+ def initialize; method_run_in_initialize; end
11
+ def method_run_in_initialize; end
12
+ end
13
+ method_double_called = false
14
+ double_creator = double_definition_creator_for(klass)
15
+ double_creator.method_run_in_initialize { method_double_called = true }
16
+ klass.new
17
+ expect(method_double_called).to eq true
18
+ end
19
+ end
20
+
21
+ context 'where methods being doubled do not already exist', methods_exist: false do
22
+ include_context 'tests for a double definition creator method that supports stubbing'
23
+ end
24
+ end
25
+
26
+ context 'where subject is an instance of a class', method_type: :instance do
27
+ it "doesn't work" do
28
+ double_creator = double_definition_creator_for(Object.new)
29
+ expect { double_creator.some_method }.to raise_error(ArgumentError)
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,39 @@
1
+ shared_context 'stub + instance_of + strong' do
2
+ include StubDefinitionCreatorHelpers
3
+
4
+ context 'where subject is a class', method_type: :class do
5
+ context 'where methods being doubled already exist', methods_exist: true do
6
+ include_context 'tests for a double definition creator method that supports stubbing'
7
+
8
+ it_behaves_like 'comparing the arity between the method and double definition'
9
+
10
+ it "lets you stub methods which are called in #initialize" do
11
+ klass = Class.new do
12
+ def initialize; method_run_in_initialize; end
13
+ def method_run_in_initialize; end
14
+ end
15
+ method_double_called = false
16
+ double_creator = double_definition_creator_for(klass)
17
+ double_creator.method_run_in_initialize { method_double_called = true }
18
+ klass.new
19
+ expect(method_double_called).to eq true
20
+ end
21
+ end
22
+
23
+ context 'where methods being doubled do not already exist', methods_exist: false do
24
+ it "doesn't work" do
25
+ klass = Class.new
26
+ double_creator = double_definition_creator_for(klass)
27
+ expect { double_creator.some_method }.to \
28
+ raise_error(RR::Errors::SubjectDoesNotImplementMethodError)
29
+ end
30
+ end
31
+ end
32
+
33
+ context 'where subject is an instance of a class', method_type: :instance do
34
+ it "doesn't work" do
35
+ double_creator = double_definition_creator_for(Object.new)
36
+ expect { double_creator.some_method }.to raise_error(ArgumentError)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,11 @@
1
+ shared_context 'stub + proxy' do
2
+ include ProxyDefinitionCreatorHelpers
3
+
4
+ context 'against instance methods', method_type: :instance do
5
+ include_context 'tests for a double definition creator method that supports stubbing'
6
+ end
7
+
8
+ context 'against class methods', method_type: :class do
9
+ include_context 'tests for a double definition creator method that supports stubbing'
10
+ end
11
+ end
@@ -0,0 +1,37 @@
1
+ shared_context 'stub + strong' do
2
+ include StubDefinitionCreatorHelpers
3
+
4
+ context 'against instance methods', method_type: :instance do
5
+ context 'that exist', methods_exist: true do
6
+ include_context 'tests for a double definition creator method that supports stubbing'
7
+
8
+ it_behaves_like 'comparing the arity between the method and double definition'
9
+ end
10
+
11
+ context 'that do not exist', methods_exist: false do
12
+ it "doesn't work" do
13
+ object = Object.new
14
+ double_creator = double_definition_creator_for(object)
15
+ expect { double_creator.some_method }.to \
16
+ raise_error(RR::Errors::SubjectDoesNotImplementMethodError)
17
+ end
18
+ end
19
+ end
20
+
21
+ context 'against class methods', method_type: :class do
22
+ context 'that exist', methods_exist: true do
23
+ include_context 'tests for a double definition creator method that supports stubbing'
24
+
25
+ it_behaves_like 'comparing the arity between the method and double definition'
26
+ end
27
+
28
+ context 'that do not exist', methods_exist: false do
29
+ it "doesn't work" do
30
+ klass = Class.new
31
+ double_creator = double_definition_creator_for(klass)
32
+ expect { double_creator.some_method }.to \
33
+ raise_error(RR::Errors::SubjectDoesNotImplementMethodError)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,57 @@
1
+ shared_context 'tests for a double definition creator method that supports stubbing' do
2
+ include DoubleDefinitionCreatorHelpers
3
+
4
+ it_behaves_like 'defining a method double that sets the implementation of that method'
5
+
6
+ context 'defining a method double with an argument expectation' do
7
+ context 'by passing arguments to the double definition directly' do
8
+ include_context 'using 1 of 2 ways to define a method double with an argument expectation without any qualifiers'
9
+
10
+ def define_double_with_argument_expectation(double_creator, method_name, *args)
11
+ double_creator.__send__(method_name, *args)
12
+ end
13
+ end
14
+
15
+ # https://github.com/rr/rr/issues/23
16
+ unless supports_strong?
17
+ context 'by using #with and arguments' do
18
+ include_context 'using 1 of 2 ways to define a method double with an argument expectation without any qualifiers'
19
+
20
+ def define_double_with_argument_expectation(double_creator, method_name, *args)
21
+ double_creator.__send__(method_name).with(*args)
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ it_behaves_like 'defining a method double qualified with #yields'
28
+ it_behaves_like 'defining method doubles using the block form of the double definition creator'
29
+ it_behaves_like 'defining a method double for sequential invocations of that method using #ordered/#then'
30
+ it_behaves_like 'an object which has a method double wrapped in an array and flattened'
31
+
32
+ if supports_proxying? && !supports_instance_of?
33
+ it_behaves_like 'defining a method double on an object which is a proxy for another object'
34
+ end
35
+
36
+ if methods_being_doubled_exist_already?
37
+ it "lets you double operator methods as well as normal ones" do
38
+ object = build_object do |subject|
39
+ double_definition_creator_for(subject).==(anything) { 'value' }
40
+ end
41
+ expect(object == :whatever).to eq 'value'
42
+ end
43
+ end
44
+
45
+ if type_of_methods_being_tested == :class && methods_being_doubled_exist_already? && !supports_instance_of?
46
+ it "in a parent class doesn't affect child classes" do
47
+ parent_class = Class.new do
48
+ def self.some_method; 'existing value'; end
49
+ end
50
+ child_class = Class.new(parent_class)
51
+ double_creator = double_definition_creator_for(parent_class)
52
+ double_creator.some_method { 'value' }
53
+ parent_class.some_method
54
+ expect(child_class.some_method).to eq 'existing value'
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,35 @@
1
+ # btakita/rr issue #44
2
+ shared_examples_for 'an object which has a method double wrapped in an array and flattened' do
3
+ include DoubleDefinitionCreatorHelpers
4
+
5
+ it "does not raise an error" do
6
+ object = build_object_with_possible_methods(some_method: -> {}) do |subject|
7
+ double_definition_creator_for(subject).some_method
8
+ end
9
+ # force RR to define method_missing
10
+ call_method_rescuing_times_called_error(object, :some_method)
11
+ expect([object].flatten).to eq [object]
12
+ end
13
+
14
+ it "honors a #to_ary that already exists" do
15
+ object = build_object_with_possible_methods(some_method: -> {}) do |subject, object|
16
+ (class << object; self; end).class_eval do
17
+ def to_ary; []; end
18
+ end
19
+ double_definition_creator_for(subject).some_method
20
+ end
21
+ # force RR to define method_missing
22
+ call_method_rescuing_times_called_error(object, :some_method)
23
+ expect([object].flatten).to eq []
24
+ end
25
+
26
+ it "is reset correctly" do
27
+ object = build_object_with_possible_methods(some_method: -> {}) do |subject|
28
+ double_definition_creator_for(subject).some_method
29
+ end
30
+ # force RR to define method_missing
31
+ call_method_rescuing_times_called_error(object, :some_method)
32
+ RR.reset
33
+ expect([object].flatten).to eq [object]
34
+ end
35
+ end
@@ -0,0 +1,31 @@
1
+ shared_examples_for 'defining method doubles using the block form of the double definition creator' do
2
+ include DoubleDefinitionCreatorHelpers
3
+
4
+ it "allows multiple methods to be doubled" do
5
+ object = build_object_with_possible_methods(
6
+ some_method: -> { 'existing value 1' },
7
+ another_method: -> { 'existing value 2' }
8
+ ) do |subject|
9
+ double_definition_creator_for(subject) do
10
+ some_method { 'value 1' }
11
+ another_method { 'value 2' }
12
+ end
13
+ end
14
+ expect_call_to_return_or_raise_times_called_error('value 1', object, :some_method)
15
+ expect_call_to_return_or_raise_times_called_error('value 2', object, :another_method)
16
+ end
17
+
18
+ it "yields rather than using instance_eval if a block argument is given" do
19
+ object = build_object_with_possible_methods(
20
+ some_method: -> { 'existing value 1' },
21
+ another_method: -> { 'existing value 2' }
22
+ ) do |subject|
23
+ double_definition_creator_for(subject) do |double_creator|
24
+ double_creator.some_method { 'value 1' }
25
+ double_creator.another_method { 'value 2' }
26
+ end
27
+ end
28
+ expect_call_to_return_or_raise_times_called_error('value 1', object, :some_method)
29
+ expect_call_to_return_or_raise_times_called_error('value 2', object, :another_method)
30
+ end
31
+ end
@@ -0,0 +1,63 @@
1
+ shared_examples_for 'comparing the arity between the method and double definition' do
2
+ it "succeeds if both have no arity" do
3
+ object = build_object_with_methods(some_method: -> {}) do |subject|
4
+ double_creator = double_definition_creator_for(subject)
5
+ double_creator.some_method
6
+ end
7
+ object.some_method
8
+ end
9
+
10
+ it "fails if the former has no arity and the latter does" do
11
+ build_object_with_methods(some_method: -> {}) do |subject|
12
+ double_creator = double_definition_creator_for(subject)
13
+ expect { double_creator.some_method(1) }.to \
14
+ raise_error(RR::Errors::SubjectHasDifferentArityError)
15
+ end
16
+ end
17
+
18
+ it "fails if the former has arity but the latter doesn't" do
19
+ build_object_with_methods(some_method: ->(arg) {}) do |subject|
20
+ double_creator = double_definition_creator_for(subject)
21
+ expect { double_creator.some_method }.to \
22
+ raise_error(RR::Errors::SubjectHasDifferentArityError)
23
+ end
24
+ end
25
+
26
+ it "succeeds if both have a finite number of arguments" do
27
+ object = build_object_with_methods(some_method: ->(arg) {}) do |subject|
28
+ double_creator = double_definition_creator_for(subject)
29
+ double_creator.some_method(1)
30
+ end
31
+ object.some_method(1)
32
+ end
33
+
34
+ it "succeeds if both have a variable number of arguments" do
35
+ object = build_object_with_methods(some_method: ->(*args) {}) do |subject|
36
+ double_creator = double_definition_creator_for(subject)
37
+ double_creator.some_method(1)
38
+ double_creator.some_method(1, 2, 3)
39
+ double_creator.some_method(1, 2)
40
+ end
41
+ object.some_method(1)
42
+ object.some_method(1, 2)
43
+ object.some_method(1, 2, 3)
44
+ end
45
+
46
+ it "succeeds if both have finite and variable number of arguments" do
47
+ object = build_object_with_methods(some_method: ->(arg1, arg2, *rest) {}) do |subject|
48
+ double_creator = double_definition_creator_for(subject)
49
+ double_creator.some_method(1, 2)
50
+ double_creator.some_method(1, 2, 3)
51
+ end
52
+ object.some_method(1, 2)
53
+ object.some_method(1, 2, 3)
54
+ end
55
+
56
+ it "fails if the finite arguments are not matched before the variable arguments" do
57
+ build_object_with_methods(some_method: ->(arg1, arg2, *rest) {}) do |subject|
58
+ double_creator = double_definition_creator_for(subject)
59
+ expect { double_creator.some_method(1) }.to \
60
+ raise_error(RR::Errors::SubjectHasDifferentArityError)
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,43 @@
1
+ # btakita/rr issue #24
2
+ # this happens when defining a double on an ActiveRecord association object
3
+ shared_examples_for 'defining a method double on an object which is a proxy for another object' do
4
+ include DoubleDefinitionCreatorHelpers
5
+
6
+ it "places the double on the proxy object and not the target object by mistake" do
7
+ target_object = build_object_with_possible_methods(some_method: -> { 'existing value' })
8
+ proxy_object = proxy_object_class.new(target_object)
9
+ expect(proxy_object.methods).to match_array(target_object.methods)
10
+ double_definition_creator_for(proxy_object).some_method { 'value' }
11
+ expect(proxy_object.some_method).to eq 'value'
12
+ end
13
+
14
+ it "resets the double correctly" do
15
+ target_object = build_object_with_possible_methods(some_method: -> { 'existing value' })
16
+ proxy_object = proxy_object_class.new(target_object)
17
+ expect(proxy_object.methods).to match_array(target_object.methods)
18
+ double_definition_creator_for(proxy_object).some_method { 'value' }
19
+ RR.reset
20
+ expect_method_to_have_value_or_be_absent('existing value', proxy_object, :some_method)
21
+ end
22
+
23
+ def proxy_object_class
24
+ Class.new do
25
+ # This matches what AssociationProxy was like as of Rails 2
26
+ instance_methods.each do |m|
27
+ undef_method m unless m.to_s =~ /^(?:nil\?|send|object_id|to_a)$|^__|^respond_to|proxy_/
28
+ end
29
+
30
+ def initialize(target)
31
+ @target = target
32
+ end
33
+
34
+ def method_missing(name, *args, &block)
35
+ if @target.respond_to?(name)
36
+ @target.__send__(name, *args, &block)
37
+ else
38
+ super
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,26 @@
1
+ shared_examples_for 'defining a method double for sequential invocations of that method using #ordered/#then' do
2
+ include DoubleDefinitionCreatorHelpers
3
+
4
+ it "works" do
5
+ object = build_object_with_possible_methods(some_method: -> {}) do |subject|
6
+ double_creator = double_definition_creator_for(subject)
7
+ double_creator.some_method { 'value 1' }.twice.ordered
8
+ double_creator.some_method { 'value 2' }.once.ordered
9
+ end
10
+
11
+ expect(object.some_method).to eq 'value 1'
12
+ expect(object.some_method).to eq 'value 1'
13
+ expect(object.some_method).to eq 'value 2'
14
+ end
15
+
16
+ it "works when using #then instead of #ordered" do
17
+ object = build_object_with_possible_methods(some_method: -> {}) do |subject|
18
+ double_definition_creator_for(subject).
19
+ some_method { 'value 1' }.once.then.
20
+ some_method { 'value 2' }.once
21
+ end
22
+
23
+ expect(object.some_method).to eq 'value 1'
24
+ expect(object.some_method).to eq 'value 2'
25
+ end
26
+ end
@@ -0,0 +1,51 @@
1
+ shared_examples_for 'defining a method double that sets the implementation of that method' do
2
+ include DoubleDefinitionCreatorHelpers
3
+
4
+ it "works when not given a block" do
5
+ expect_that_double_can_be_defined_without_block
6
+ end
7
+
8
+ context 'by giving a block' do
9
+ it "replaces the implementation with the block" do
10
+ expect_that_double_sets_implementation do |double_creator, method_name, block|
11
+ double_creator.__send__(method_name, &block)
12
+ end
13
+ end
14
+
15
+ it "resets the double correctly" do
16
+ expect_that_double_sets_implementation_and_resets do |double_creator, method_name, block|
17
+ double_creator.__send__(method_name, &block)
18
+ end
19
+ end
20
+ end
21
+
22
+ context 'by using #returns' do
23
+ context 'with a block' do
24
+ it "replaces the implementation with the block" do
25
+ expect_that_double_sets_implementation do |double_creator, method_name, block|
26
+ double_creator.__send__(method_name).returns(&block)
27
+ end
28
+ end
29
+
30
+ it "resets the double correctly" do
31
+ expect_that_double_sets_implementation_and_resets do |double_creator, method_name, block|
32
+ double_creator.__send__(method_name).returns(&block)
33
+ end
34
+ end
35
+ end
36
+
37
+ context 'with a straight argument' do
38
+ it "makes the method return the argument" do
39
+ expect_that_double_sets_value do |double_creator, method_name, value|
40
+ double_creator.__send__(method_name).returns(value)
41
+ end
42
+ end
43
+
44
+ it "resets the double correctly" do
45
+ expect_that_double_sets_value_and_resets do |double, method_name, value|
46
+ double_creator.__send__(method_name).returns(value)
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,81 @@
1
+ shared_examples_for 'defining a method double qualified with #yields' do
2
+ include DoubleDefinitionCreatorHelpers
3
+
4
+ context 'without arguments' do
5
+ it "inserts a yield that passes no arguments" do
6
+ object = build_object_with_possible_methods(some_method: -> {}) do |subject|
7
+ double_definition_creator_for(subject).some_method.yields
8
+ end
9
+ x = 0
10
+ object.some_method { x = 1 }
11
+ expect(x).to eq 1
12
+ end
13
+
14
+ it "does not affect setting the implementation otherwise" do
15
+ object = build_object_with_possible_methods(some_method: -> { 'existing value' }) do |subject|
16
+ double_definition_creator_for(subject).some_method { 'value' }.yields
17
+ end
18
+ expect(object.some_method { }).to eq 'value'
19
+ end
20
+
21
+ it "also lets you set the implementation in preference to #returns" do
22
+ object = build_object_with_possible_methods(some_method: -> { 'existing value' }) do |subject|
23
+ double_definition_creator_for(subject).some_method.yields { 'value' }
24
+ end
25
+ expect(object.some_method { }).to eq 'value'
26
+ end
27
+
28
+ it "is reset correctly" do
29
+ object = build_object_with_possible_methods(some_method: -> {}) do |subject|
30
+ double_definition_creator_for(subject).some_method.yields
31
+ end
32
+ RR.reset
33
+ x = 0
34
+ if methods_being_doubled_exist_already?
35
+ object.some_method { x = 1 }
36
+ expect(x).to eq 0
37
+ else
38
+ expect_method_to_not_exist(object, :some_method)
39
+ end
40
+ end
41
+ end
42
+
43
+ context 'with arguments' do
44
+ it "inserts a yield that passes those arguments" do
45
+ object = build_object_with_possible_methods(some_method: -> {}) do |subject|
46
+ double_definition_creator_for(subject).some_method.yields(1)
47
+ end
48
+ x = 0
49
+ object.some_method {|a| x = a }
50
+ expect(x).to eq 1
51
+ end
52
+
53
+ it "does not affect setting the implementation otherwise" do
54
+ object = build_object_with_possible_methods(some_method: -> { 'existing value' }) do |subject|
55
+ double_definition_creator_for(subject).some_method { 'value' }.yields(1)
56
+ end
57
+ expect(object.some_method { }).to eq 'value'
58
+ end
59
+
60
+ it "also lets you set the implementation in preference to #returns" do
61
+ object = build_object_with_possible_methods(some_method: -> { 'existing value' }) do |subject|
62
+ double_definition_creator_for(subject).some_method.yields(1) { 'value' }
63
+ end
64
+ expect(object.some_method { }).to eq 'value'
65
+ end
66
+
67
+ it "is reset correctly" do
68
+ object = build_object_with_possible_methods(some_method: -> {}) do |subject|
69
+ double_definition_creator_for(subject).some_method.yields(1)
70
+ end
71
+ RR.reset
72
+ if methods_being_doubled_exist_already?
73
+ x = 0
74
+ object.some_method {|a| x = a }
75
+ expect(x).to eq 0
76
+ else
77
+ expect_method_to_not_exist(object, :some_method)
78
+ end
79
+ end
80
+ end
81
+ end