spy 1.0.2 → 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
|