spy 1.0.2 → 1.0.4
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.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +38 -0
- data/.tool-versions +1 -1
- data/CHANGELOG.md +16 -0
- data/README.md +3 -4
- data/lib/spy/call_log.rb +6 -3
- data/lib/spy/subroutine.rb +15 -31
- data/lib/spy/version.rb +1 -1
- data/spy.gemspec +1 -1
- data/test/integration/test_class_method.rb +24 -0
- data/test/spy/test_subroutine.rb +22 -0
- data/test/spy/test_unhook.rb +76 -0
- data/test/support/pen.rb +4 -0
- metadata +9 -37
- data/.travis.yml +0 -13
- data/spec/spec_helper.rb +0 -41
- data/spec/spy/and_call_original_spec.rb +0 -152
- data/spec/spy/and_yield_spec.rb +0 -123
- data/spec/spy/any_instance_spec.rb +0 -518
- data/spec/spy/hash_excluding_matcher_spec.rb +0 -63
- data/spec/spy/hash_including_matcher_spec.rb +0 -86
- data/spec/spy/mutate_const_spec.rb +0 -471
- data/spec/spy/nil_expectation_warning_spec.rb +0 -56
- data/spec/spy/null_object_mock_spec.rb +0 -79
- data/spec/spy/partial_mock_spec.rb +0 -81
- data/spec/spy/passing_argument_matchers_spec.rb +0 -140
- data/spec/spy/serialization_spec.rb +0 -116
- data/spec/spy/stash_spec.rb +0 -47
- data/spec/spy/stub_implementation_spec.rb +0 -64
- data/spec/spy/stub_spec.rb +0 -79
- data/spec/spy/to_ary_spec.rb +0 -40
@@ -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
|
-
|
data/spec/spy/and_yield_spec.rb
DELETED
@@ -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
|
-
|