spy 1.0.3 → 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eb02855e84ed97ae778d5983b8bba3e5839a6593416336a18240beb759f82b7f
4
- data.tar.gz: df92498cacaab913d6d71d6d3e34778140d7367f741a1f1d750e96cbc2353a19
3
+ metadata.gz: 46c870bafa6e5402e585dc44ea855f5e22a8087b4c14f70fad8794b39ac425a0
4
+ data.tar.gz: c9552993d8b0e335defead206a238c0342ea461102722f6702f04ae8a823f100
5
5
  SHA512:
6
- metadata.gz: 72e822dfc3517b8bcc4d26d9ffc0db333acd4526673a765de0a19f4396292834bd0402a307d31d6ba226c5f9017a2813fba53738d5784dc00fc0aa0e66720869
7
- data.tar.gz: 35b2c58f79ef8da6c462ba1a5739ddc2705df1544a2f75c14ecb9731c60b5f33337f94056dbf1803480699d6729f0410985194cbfe4d376852cf5417d352b8c2
6
+ metadata.gz: 5b476de3ea3a4f01a85ed3f99d51ed7c38785f67c9c7b565607e6e0edd027eeb643bc2fe43a92b8bdcfc7054e149c6e75022489bccaa3b7678f4239263152094
7
+ data.tar.gz: 16d976fa766805c685f7198fe219a55802d29a4d560ec7f984c229c751905c81fe0622a8887fc71c0c87845a48d40d283fdb4f0411d2c3ded2d72673bddfe1e1
@@ -0,0 +1,38 @@
1
+ # This workflow uses actions that are not certified by GitHub.
2
+ # They are provided by a third-party and are governed by
3
+ # separate terms of service, privacy policy, and support
4
+ # documentation.
5
+ # This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
6
+ # For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
7
+
8
+ name: Ruby
9
+
10
+ on:
11
+ push:
12
+ branches: [ "master" ]
13
+ pull_request:
14
+ branches: [ "master" ]
15
+
16
+ permissions:
17
+ contents: read
18
+
19
+ jobs:
20
+ test:
21
+
22
+ runs-on: ubuntu-latest
23
+ strategy:
24
+ matrix:
25
+ ruby-version: ['2.7', '3.0', '3.1']
26
+
27
+ steps:
28
+ - uses: actions/checkout@v3
29
+ - name: Set up Ruby
30
+ # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
31
+ # change this to (see https://github.com/ruby/setup-ruby#versioning):
32
+ # uses: ruby/setup-ruby@v1
33
+ uses: ruby/setup-ruby@0a29871fe2b0200a17a4497bae54fe5df0d973aa # v1.115.3
34
+ with:
35
+ ruby-version: ${{ matrix.ruby-version }}
36
+ bundler-cache: true # runs 'bundle install' and caches installed gems automatically
37
+ - name: Run tests
38
+ run: bundle exec rake
data/.tool-versions CHANGED
@@ -1 +1 @@
1
- ruby 2.7.0
1
+ ruby 3.1.2
data/CHANGELOG.md CHANGED
@@ -1,3 +1,23 @@
1
+ ## Spy 1.0.4 (December 21th, 2022) ##
2
+
3
+ * remove usage of #present? (@ryanong)
4
+
5
+ ## Spy 1.0.4 (December 21th, 2022) ##
6
+
7
+ * Hash as argument got turned into keyword arguments (@svenpl)
8
+ * drop support for ruby older than 2.7 (@ryanong)
9
+
10
+ ## Spy 1.0.3 (September 15, 2022) ##
11
+
12
+ * Fix private method call errors for older ruby versions (@dylanahsmith)
13
+ * `Spy.on_instance_method` and `and_call_through` on `#to_ary-able` class causes an error (@mizukami234)
14
+ * Fix `and_return` on class method (@jfirebaugh)
15
+
16
+ ## Spy 1.0.2 (January 10, 2022) ##
17
+
18
+ * Fix subroutine call with hash as last arg (@dtheo-ad)
19
+ * Ruby 2.7+ support (@casperisfine)
20
+
1
21
  ## Spy 1.0.1 (August 20th, 2020) ##
2
22
 
3
23
  * Fix call_through w/ instance methods (@lreeves)
data/README.md CHANGED
@@ -9,8 +9,7 @@
9
9
 
10
10
  Spy is a lightweight stubbing framework with support for method spies, constant stubs, and object mocks.
11
11
 
12
- Spy supports ruby 2.1.0+.
13
- For versions less than 2.1 use v0.4.5
12
+ Spy supports ruby 2.7.0+.
14
13
 
15
14
  Spy features that were completed were tested against the rspec-mocks tests so it covers all cases that rspec-mocks does.
16
15
 
@@ -47,7 +46,7 @@ Fail faster, code faster.
47
46
  * you can usually just check the call logs.
48
47
  * if you do need to use this. It is probably a code smell. You either need to abstract your method more or add separate tests.
49
48
  * you want to use dumb double, Spy has smart mocks, they are better
50
- * you use `mock_model` and `stub_model` (I want to impliment this soon)
49
+ * you use `mock_model` and `stub_model`
51
50
 
52
51
  ## Installation
53
52
 
@@ -87,7 +86,7 @@ Spy::Subroutine.new(book, :flamethrower).hook(force:true).and_return("burnninant
87
86
  ```
88
87
 
89
88
  You can also stub instance methods of Classes and Modules. This is equivalent to
90
- rspec-mock's `Module#any_instance`
89
+ rspec-mock's `allow_any_instance_of(Module)`
91
90
 
92
91
  ```ruby
93
92
  Spy.on_instance_method(Book, :title).and_return("Cannery Row")
data/lib/spy/call_log.rb CHANGED
@@ -10,6 +10,9 @@ module Spy
10
10
  # @!attribute [r] args
11
11
  # @return [Array] arguments were sent to the method
12
12
  #
13
+ # @!attribute [r] kwargs
14
+ # @return [Array] keyword arguments were sent to the method
15
+ #
13
16
  # @!attribute [r] block
14
17
  # @return [Proc] the block that was sent to the method
15
18
  #
@@ -17,10 +20,10 @@ module Spy
17
20
  # @return The result of the method of being stubbed, or called through
18
21
 
19
22
 
20
- attr_reader :object, :called_from, :args, :block, :result
23
+ attr_reader :object, :called_from, :args, :kwargs, :block, :result
21
24
 
22
- def initialize(object, called_from, args, block, result)
23
- @object, @called_from, @args, @block, @result = object, called_from, args, block, result
25
+ def initialize(object, called_from, args, kwargs, block, result)
26
+ @object, @called_from, @args, @kwargs, @block, @result = object, called_from, args, kwargs, block, result
24
27
  end
25
28
  end
26
29
  end
@@ -201,26 +201,28 @@ module Spy
201
201
  # check if the method was called with the exact arguments
202
202
  # @param args Arguments that should have been sent to the method
203
203
  # @return [Boolean]
204
- def has_been_called_with?(*args, &block)
204
+ def has_been_called_with?(*args, **kwargs, &block)
205
205
  raise NeverHookedError unless @was_hooked
206
- match = block_given? ? block : proc { |call| call.args == args }
206
+ match = block_given? ? block : proc { |call| call.args == args && call.kwargs == kwargs }
207
207
  calls.any?(&match)
208
208
  end
209
209
 
210
210
  # invoke that the method has been called. You really shouldn't use this
211
211
  # method.
212
- def invoke(object, args, block, called_from)
213
- check_arity!(args.size)
212
+ def invoke(object, args, kwargs, block, called_from)
213
+ arity = args.size
214
+ arity += 1 if !kwargs&.empty?
215
+ check_arity!(arity)
214
216
 
215
217
  result =
216
218
  if @call_through
217
- call_plan(build_call_through_plan(object), block, *args)
219
+ call_plan(build_call_through_plan(object), block, *args, **kwargs)
218
220
  elsif @plan
219
221
  check_for_too_many_arguments!(@plan)
220
- call_plan(@plan, block, *args)
222
+ call_plan(@plan, block, *args, **kwargs)
221
223
  end
222
224
  ensure
223
- calls << CallLog.new(object, called_from, args, block, result)
225
+ calls << CallLog.new(object, called_from, args, kwargs, block, result)
224
226
  end
225
227
 
226
228
  # reset the call log
@@ -237,11 +239,12 @@ module Spy
237
239
  # we use eval to set the spy object id as a parameter so it can be extracted
238
240
  # and looked up later using `Method#parameters`
239
241
  SPY_ARGS_PREFIX='__spy_args_'.freeze
242
+ SPY_KWARGS_PREFIX='__spy_kwargs_'.freeze
240
243
  def override_method
241
244
  eval <<-METHOD, binding, __FILE__, __LINE__ + 1
242
245
  __method_spy__ = self
243
- lambda do |*#{SPY_ARGS_PREFIX}#{self.object_id}, &block|
244
- __method_spy__.invoke(self, #{SPY_ARGS_PREFIX}#{self.object_id}, block, caller(1)[0])
246
+ lambda do |*#{SPY_ARGS_PREFIX}#{self.object_id}, **#{SPY_KWARGS_PREFIX}#{self.object_id}, &block|
247
+ __method_spy__.invoke(self, #{SPY_ARGS_PREFIX}#{self.object_id}, #{SPY_KWARGS_PREFIX}#{self.object_id}, block, caller(1)[0])
245
248
  end
246
249
  METHOD
247
250
  end
@@ -345,23 +348,8 @@ module Spy
345
348
  end
346
349
  end
347
350
 
348
- def call_plan(plan, block, *args)
349
- if ruby_27_last_arg_hash?(args)
350
- *prefix, last = args
351
- plan.call(*prefix, **last, &block)
352
- else
353
- plan.call(*args, &block)
354
- end
355
- end
356
-
357
- # Ruby 2.7 gives a deprecation warning about passing hash as last argument for a method
358
- # with a double-splat operator (**), and Ruby 3 raises an ArgumentError exception.
359
- # This checks if args has a hash as last element to extract it and pass it with double-splat to avoid an exception.
360
- def ruby_27_last_arg_hash?(args)
361
- last = args.last
362
- last.instance_of?(Hash) &&
363
- !last.empty? &&
364
- Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.7.0")
351
+ def call_plan(plan, block, *args, **kwargs)
352
+ plan.call(*args, **kwargs, &block)
365
353
  end
366
354
 
367
355
  class << self
data/lib/spy/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Spy
2
- VERSION = "1.0.3"
2
+ VERSION = "1.0.5"
3
3
  end
data/spy.gemspec CHANGED
@@ -6,7 +6,7 @@ require 'spy/version'
6
6
  Gem::Specification.new do |gem|
7
7
  gem.name = "spy"
8
8
  gem.version = Spy::VERSION
9
- gem.required_ruby_version = '>= 2.1.0'
9
+ gem.required_ruby_version = '>= 2.7.0'
10
10
  gem.license = 'MIT'
11
11
  gem.authors = ["Ryan Ong"]
12
12
  gem.email = ["ryanong@gmail.com"]
@@ -150,6 +150,14 @@ module Spy
150
150
  assert_equal string, result
151
151
  end
152
152
 
153
+ def test_spy_and_call_through_with_hash_and_keyword_args
154
+ spy_on(@pen, 'hash_and_keyword_arg').and_call_through
155
+ hsh = { hello: 'world' }
156
+
157
+ assert_equal [hsh, nil], @pen.hash_and_keyword_arg(hsh)
158
+ assert_equal [hsh, 'foo'], @pen.hash_and_keyword_arg(hsh, keyword: 'foo')
159
+ end
160
+
153
161
  def test_spy_and_call_through_returns_original_method_result
154
162
  string = "hello world"
155
163
 
@@ -237,6 +245,20 @@ module Spy
237
245
  assert pen_write_spy.has_been_called_with?("hello")
238
246
  end
239
247
 
248
+ def test_has_been_called_with_kwargs
249
+ pen_write_spy = spy_on(@pen, :opt_kwargs)
250
+ refute pen_write_spy.has_been_called_with?("hello")
251
+
252
+ @pen.opt_kwargs("hello")
253
+ assert pen_write_spy.has_been_called_with?("hello")
254
+
255
+ @pen.opt_kwargs("world", opt: "hello")
256
+ assert pen_write_spy.has_been_called_with?("world", opt: "hello")
257
+
258
+ @pen.opt_kwargs("hello world", opt: "world", opt2: "hello")
259
+ assert pen_write_spy.has_been_called_with?("hello world", opt: "world", opt2: "hello")
260
+ end
261
+
240
262
  def test_spy_hook_records_number_of_calls2
241
263
  args = ["hello world"]
242
264
  block = Proc.new {}
data/test/support/pen.rb CHANGED
@@ -37,6 +37,10 @@ class Pen
37
37
  write("#{hello} #{name}")
38
38
  end
39
39
 
40
+ def hash_and_keyword_arg(hsh, keyword: nil)
41
+ [hsh, keyword]
42
+ end
43
+
40
44
  def public_method
41
45
  end
42
46
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spy
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Ong
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-09-15 00:00:00.000000000 Z
11
+ date: 2022-12-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pry
@@ -117,9 +117,9 @@ executables: []
117
117
  extensions: []
118
118
  extra_rdoc_files: []
119
119
  files:
120
+ - ".github/workflows/ruby.yml"
120
121
  - ".gitignore"
121
122
  - ".tool-versions"
122
- - ".travis.yml"
123
123
  - ".yardopts"
124
124
  - CHANGELOG.md
125
125
  - Gemfile
@@ -139,22 +139,6 @@ files:
139
139
  - lib/spy/nest.rb
140
140
  - lib/spy/subroutine.rb
141
141
  - lib/spy/version.rb
142
- - spec/spec_helper.rb
143
- - spec/spy/and_call_original_spec.rb
144
- - spec/spy/and_yield_spec.rb
145
- - spec/spy/any_instance_spec.rb
146
- - spec/spy/hash_excluding_matcher_spec.rb
147
- - spec/spy/hash_including_matcher_spec.rb
148
- - spec/spy/mutate_const_spec.rb
149
- - spec/spy/nil_expectation_warning_spec.rb
150
- - spec/spy/null_object_mock_spec.rb
151
- - spec/spy/partial_mock_spec.rb
152
- - spec/spy/passing_argument_matchers_spec.rb
153
- - spec/spy/serialization_spec.rb
154
- - spec/spy/stash_spec.rb
155
- - spec/spy/stub_implementation_spec.rb
156
- - spec/spy/stub_spec.rb
157
- - spec/spy/to_ary_spec.rb
158
142
  - spy.gemspec
159
143
  - test/integration/test_api.rb
160
144
  - test/integration/test_class_method.rb
@@ -179,7 +163,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
179
163
  requirements:
180
164
  - - ">="
181
165
  - !ruby/object:Gem::Version
182
- version: 2.1.0
166
+ version: 2.7.0
183
167
  required_rubygems_version: !ruby/object:Gem::Requirement
184
168
  requirements:
185
169
  - - ">="
@@ -192,22 +176,6 @@ specification_version: 4
192
176
  summary: A simple modern mocking library that uses the spy pattern and checks method's
193
177
  existence and arity.
194
178
  test_files:
195
- - spec/spec_helper.rb
196
- - spec/spy/and_call_original_spec.rb
197
- - spec/spy/and_yield_spec.rb
198
- - spec/spy/any_instance_spec.rb
199
- - spec/spy/hash_excluding_matcher_spec.rb
200
- - spec/spy/hash_including_matcher_spec.rb
201
- - spec/spy/mutate_const_spec.rb
202
- - spec/spy/nil_expectation_warning_spec.rb
203
- - spec/spy/null_object_mock_spec.rb
204
- - spec/spy/partial_mock_spec.rb
205
- - spec/spy/passing_argument_matchers_spec.rb
206
- - spec/spy/serialization_spec.rb
207
- - spec/spy/stash_spec.rb
208
- - spec/spy/stub_implementation_spec.rb
209
- - spec/spy/stub_spec.rb
210
- - spec/spy/to_ary_spec.rb
211
179
  - test/integration/test_api.rb
212
180
  - test/integration/test_class_method.rb
213
181
  - test/integration/test_constant_spying.rb
data/.travis.yml DELETED
@@ -1,13 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - '2.1'
4
- - '2.5'
5
- - '2.7'
6
- - jruby
7
- - ruby-head
8
- - rbx-3
9
- matrix:
10
- allow_failures:
11
- - rvm: ruby-head
12
- - rvm: rbx-3
13
- - rvm: jruby
data/spec/spec_helper.rb DELETED
@@ -1,41 +0,0 @@
1
- require "rspec/core"
2
- require "rspec/matchers"
3
- require "rspec/expectations"
4
- require "spy"
5
- require "pry"
6
- require "pry-nav"
7
-
8
- RSpec::Matchers.define :include_method do |expected|
9
- match do |actual|
10
- actual.map { |m| m.to_s }.include?(expected.to_s)
11
- end
12
- end
13
-
14
- RSpec.configure do |config|
15
- config.color_enabled = true
16
- config.order = :random
17
- config.run_all_when_everything_filtered = true
18
- config.treat_symbols_as_metadata_keys_with_true_values = true
19
- config.filter_run_including :focus
20
- config.filter_run_excluding :broken => true
21
- config.mock_with :absolutely_nothing
22
-
23
- config.expect_with :rspec do |expectations|
24
- expectations.syntax = :expect
25
- end
26
-
27
- old_verbose = nil
28
- config.before(:each, :silence_warnings) do
29
- old_verbose = $VERBOSE
30
- $VERBOSE = nil
31
- end
32
-
33
- config.after(:each, :silence_warnings) do
34
- $VERBOSE = old_verbose
35
- end
36
-
37
- config.after(:each) do
38
- Spy.teardown
39
- end
40
- end
41
-
@@ -1,152 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe "and_call_through" do
4
- context "on a partial mock object" do
5
- let(:klass) do
6
- Class.new do
7
- def meth_1
8
- :original
9
- end
10
-
11
- def meth_2(x)
12
- yield x, :additional_yielded_arg
13
- end
14
-
15
- def self.new_instance
16
- new
17
- end
18
- end
19
- end
20
-
21
- let(:instance) { klass.new }
22
-
23
- it 'passes the received message through to the original method' do
24
- spy = Spy.on(instance, :meth_1).and_call_through
25
- expect(instance.meth_1).to eq(:original)
26
- expect(spy).to have_been_called
27
- end
28
-
29
- it 'passes args and blocks through to the original method' do
30
- spy = Spy.on(instance, :meth_2).and_call_through
31
- value = instance.meth_2(:submitted_arg) { |a, b| [a, b] }
32
- expect(value).to eq([:submitted_arg, :additional_yielded_arg])
33
- expect(spy).to have_been_called
34
- end
35
-
36
- it 'works for singleton methods' do
37
- def instance.foo; :bar; end
38
- spy = Spy.on(instance, :foo).and_call_through
39
- expect(instance.foo).to eq(:bar)
40
- expect(spy).to have_been_called
41
- end
42
-
43
- it 'works for methods added through an extended module' do
44
- instance.extend Module.new { def foo; :bar; end }
45
- spy = Spy.on(instance, :foo).and_call_through
46
- expect(instance.foo).to eq(:bar)
47
- expect(spy).to have_been_called
48
- end
49
-
50
- it "works for method added through an extended module onto a class's ancestor" do
51
- sub_sub_klass = Class.new(Class.new(klass))
52
- klass.extend Module.new { def foo; :bar; end }
53
- spy = Spy.on(sub_sub_klass, :foo).and_call_through
54
- expect(sub_sub_klass.foo).to eq(:bar)
55
- expect(spy).to have_been_called
56
- end
57
-
58
- it "finds the method on the most direct ancestor even if the method " +
59
- "is available on more distant ancestors" do
60
- klass.extend Module.new { def foo; :klass_bar; end }
61
- sub_klass = Class.new(klass)
62
- sub_klass.extend Module.new { def foo; :sub_klass_bar; end }
63
- spy = Spy.on(sub_klass, :foo).and_call_through
64
- expect(sub_klass.foo).to eq(:sub_klass_bar)
65
- expect(spy).to have_been_called
66
- end
67
-
68
- it 'works for class methods defined on a superclass' do
69
- subclass = Class.new(klass)
70
- spy = Spy.on(subclass, :new_instance).and_call_through
71
- expect(subclass.new_instance).to be_a(subclass)
72
- expect(spy).to have_been_called
73
- end
74
-
75
- it 'works for class methods defined on a grandparent class' do
76
- sub_subclass = Class.new(Class.new(klass))
77
- spy = Spy.on(sub_subclass, :new_instance).and_call_through
78
- expect(sub_subclass.new_instance).to be_a(sub_subclass)
79
- expect(spy).to have_been_called
80
- end
81
-
82
- it 'works for class methods defined on the Class class' do
83
- spy = Spy.on(klass, :new).and_call_through
84
- expect(klass.new).to be_an_instance_of(klass)
85
- expect(spy).to have_been_called
86
- end
87
-
88
- it "works for instance methods defined on the object's class's superclass" do
89
- subclass = Class.new(klass)
90
- inst = subclass.new
91
- spy = Spy.on(inst, :meth_1).and_call_through
92
- expect(inst.meth_1).to eq(:original)
93
- expect(spy).to have_been_called
94
- end
95
-
96
- it 'works for aliased methods' do
97
- klass = Class.new do
98
- class << self
99
- alias alternate_new new
100
- end
101
- end
102
-
103
- spy = Spy.on(klass, :alternate_new).and_call_through
104
- expect(klass.alternate_new).to be_an_instance_of(klass)
105
- expect(spy).to have_been_called
106
- end
107
-
108
- context 'on an object that defines method_missing' do
109
- before do
110
- klass.class_eval do
111
- def respond_to_missing?(name, _)
112
- if name.to_s == "greet_jack"
113
- true
114
- else
115
- super
116
- end
117
- end
118
-
119
- def method_missing(name, *args)
120
- if name.to_s == "greet_jack"
121
- "Hello, jack"
122
- else
123
- super
124
- end
125
- end
126
- end
127
- end
128
-
129
- it 'works when the method_missing definition handles the message' do
130
- spy = Spy.on(instance, :greet_jack).and_call_through
131
- expect(instance.greet_jack).to eq("Hello, jack")
132
- expect(spy).to have_been_called
133
- end
134
-
135
- it 'raises an error on invocation if method_missing does not handle the message' do
136
- Spy::Subroutine.new(instance, :not_a_handled_message).hook(force: true).and_call_through
137
-
138
- # Note: it should raise a NoMethodError (and usually does), but
139
- # due to a weird rspec-expectations issue (see #183) it sometimes
140
- # raises a `NameError` when a `be_xxx` predicate matcher has been
141
- # recently used. `NameError` is the superclass of `NoMethodError`
142
- # so this example will pass regardless.
143
- # If/when we solve the rspec-expectations issue, this can (and should)
144
- # be changed to `NoMethodError`.
145
- expect {
146
- instance.not_a_handled_message
147
- }.to raise_error(NameError, /not_a_handled_message/)
148
- end
149
- end
150
- end
151
- end
152
-
@@ -1,123 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe "Spy" do
4
-
5
- class Foo
6
- def method_that_accepts_a_block(&block)
7
- end
8
- end
9
-
10
- let(:obj) { Foo.new }
11
-
12
- describe "#and_yield" do
13
- context "with eval context as block argument" do
14
-
15
- it "evaluates the supplied block as it is read" do
16
- evaluated = false
17
- Spy.on(obj, :method_that_accepts_a_block).and_yield do |eval_context|
18
- evaluated = true
19
- end
20
- expect(evaluated).to be_true
21
- end
22
-
23
- it "passes an eval context object to the supplied block" do
24
- Spy.on(obj, :method_that_accepts_a_block).and_yield do |eval_context|
25
- expect(eval_context).not_to be_nil
26
- end
27
- end
28
-
29
- it "evaluates the block passed to the stubbed method in the context of the supplied eval context" do
30
- expected_eval_context = nil
31
- actual_eval_context = nil
32
-
33
- Spy.on(obj, :method_that_accepts_a_block).and_yield do |eval_context|
34
- expected_eval_context = eval_context
35
- end
36
-
37
- obj.method_that_accepts_a_block do
38
- actual_eval_context = self
39
- end
40
-
41
- expect(actual_eval_context).to equal(expected_eval_context)
42
- end
43
-
44
- context "and no yielded arguments" do
45
-
46
- it "passes when expectations set on the eval context are met" do
47
- configured_eval_context = nil
48
- context_foo_spy = nil
49
- Spy.on(obj, :method_that_accepts_a_block).and_yield do |eval_context|
50
- configured_eval_context = eval_context
51
- context_foo_spy = Spy::Subroutine.new(configured_eval_context, :foo).hook(force: true)
52
- end
53
-
54
- obj.method_that_accepts_a_block do
55
- foo
56
- end
57
-
58
- expect(context_foo_spy).to have_been_called
59
- end
60
-
61
- it "fails when expectations set on the eval context are not met" do
62
- configured_eval_context = nil
63
- context_foo_spy = nil
64
- Spy.on(obj, :method_that_accepts_a_block).and_yield do |eval_context|
65
- configured_eval_context = eval_context
66
- context_foo_spy = Spy::Subroutine.new(configured_eval_context, :foo).hook(force: true)
67
- end
68
-
69
- obj.method_that_accepts_a_block do
70
- # foo is not called here
71
- end
72
-
73
- expect(context_foo_spy).to_not have_been_called
74
- end
75
-
76
- end
77
-
78
- context "and yielded arguments" do
79
-
80
- it "passes when expectations set on the eval context and yielded arguments are met" do
81
- configured_eval_context = nil
82
- yielded_arg = Object.new
83
- context_foo_spy = nil
84
- Spy.on(obj, :method_that_accepts_a_block).and_yield(yielded_arg) do |eval_context|
85
- configured_eval_context = eval_context
86
- context_foo_spy = Spy::Subroutine.new(configured_eval_context, :foo).hook(force: true)
87
- Spy::Subroutine.new(yielded_arg, :bar).hook(force: true)
88
- end
89
-
90
- obj.method_that_accepts_a_block do |obj|
91
- obj.bar
92
- foo
93
- end
94
-
95
- expect(context_foo_spy).to have_been_called
96
- expect(Spy.get(yielded_arg, :bar)).to have_been_called
97
- end
98
-
99
- it "fails when expectations set on the eval context and yielded arguments are not met" do
100
- configured_eval_context = nil
101
- yielded_arg = Object.new
102
- context_foo_spy = nil
103
- Spy.on(obj, :method_that_accepts_a_block).and_yield(yielded_arg) do |eval_context|
104
- configured_eval_context = eval_context
105
- context_foo_spy = Spy::Subroutine.new(configured_eval_context, :foo).hook(force: true)
106
- Spy::Subroutine.new(yielded_arg, :bar).hook(force: true)
107
- end
108
-
109
- obj.method_that_accepts_a_block do |obj|
110
- # obj.bar is not called here
111
- # foo is not called here
112
- end
113
-
114
- expect(context_foo_spy).to_not have_been_called
115
- expect(Spy.get(yielded_arg, :bar)).to_not have_been_called
116
- end
117
-
118
- end
119
-
120
- end
121
- end
122
- end
123
-