spy 1.0.1 → 1.0.5
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 +20 -0
- data/README.md +3 -4
- data/lib/spy/call_log.rb +6 -3
- data/lib/spy/subroutine.rb +42 -45
- 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 +102 -0
- data/test/spy/test_unhook.rb +76 -0
- data/test/support/pen.rb +10 -0
- metadata +12 -40
- 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,140 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module Spy
|
4
|
-
describe "Matchers", :broken do
|
5
|
-
before(:each) do
|
6
|
-
@double = double('double')
|
7
|
-
Spy.on(Kernel, :warn)
|
8
|
-
end
|
9
|
-
|
10
|
-
after(:each) do
|
11
|
-
@double.rspec_verify
|
12
|
-
end
|
13
|
-
|
14
|
-
context "handling argument matchers" do
|
15
|
-
it "accepts true as boolean()" do
|
16
|
-
@double.should_receive(:random_call).with(boolean())
|
17
|
-
@double.random_call(true)
|
18
|
-
end
|
19
|
-
|
20
|
-
it "accepts false as boolean()" do
|
21
|
-
@double.should_receive(:random_call).with(boolean())
|
22
|
-
@double.random_call(false)
|
23
|
-
end
|
24
|
-
|
25
|
-
it "accepts fixnum as kind_of(Numeric)" do
|
26
|
-
@double.should_receive(:random_call).with(kind_of(Numeric))
|
27
|
-
@double.random_call(1)
|
28
|
-
end
|
29
|
-
|
30
|
-
it "accepts float as an_instance_of(Numeric)" do
|
31
|
-
@double.should_receive(:random_call).with(kind_of(Numeric))
|
32
|
-
@double.random_call(1.5)
|
33
|
-
end
|
34
|
-
|
35
|
-
it "accepts fixnum as instance_of(Fixnum)" do
|
36
|
-
@double.should_receive(:random_call).with(instance_of(Fixnum))
|
37
|
-
@double.random_call(1)
|
38
|
-
end
|
39
|
-
|
40
|
-
it "does NOT accept fixnum as instance_of(Numeric)" do
|
41
|
-
@double.should_not_receive(:random_call).with(instance_of(Numeric))
|
42
|
-
@double.random_call(1)
|
43
|
-
end
|
44
|
-
|
45
|
-
it "does NOT accept float as instance_of(Numeric)" do
|
46
|
-
@double.should_not_receive(:random_call).with(instance_of(Numeric))
|
47
|
-
@double.random_call(1.5)
|
48
|
-
end
|
49
|
-
|
50
|
-
it "accepts string as anything()" do
|
51
|
-
@double.should_receive(:random_call).with("a", anything(), "c")
|
52
|
-
@double.random_call("a", "whatever", "c")
|
53
|
-
end
|
54
|
-
|
55
|
-
it "matches duck type with one method" do
|
56
|
-
@double.should_receive(:random_call).with(duck_type(:length))
|
57
|
-
@double.random_call([])
|
58
|
-
end
|
59
|
-
|
60
|
-
it "matches duck type with two methods" do
|
61
|
-
@double.should_receive(:random_call).with(duck_type(:abs, :div))
|
62
|
-
@double.random_call(1)
|
63
|
-
end
|
64
|
-
|
65
|
-
it "matches no args against any_args()" do
|
66
|
-
@double.should_receive(:random_call).with(any_args)
|
67
|
-
@double.random_call()
|
68
|
-
end
|
69
|
-
|
70
|
-
it "matches one arg against any_args()" do
|
71
|
-
@double.should_receive(:random_call).with(any_args)
|
72
|
-
@double.random_call("a string")
|
73
|
-
end
|
74
|
-
|
75
|
-
it "matches no args against no_args()" do
|
76
|
-
@double.should_receive(:random_call).with(no_args)
|
77
|
-
@double.random_call()
|
78
|
-
end
|
79
|
-
|
80
|
-
it "matches hash with hash_including same hash" do
|
81
|
-
@double.should_receive(:random_call).with(hash_including(:a => 1))
|
82
|
-
@double.random_call(:a => 1)
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
context "handling block matchers" do
|
87
|
-
it "matches arguments against RSpec expectations" do
|
88
|
-
@double.should_receive(:random_call).with {|arg1, arg2, arr, *rest|
|
89
|
-
expect(arg1).to eq 5
|
90
|
-
expect(arg2).to have_at_least(3).characters
|
91
|
-
expect(arg2).to have_at_most(10).characters
|
92
|
-
expect(arr.map {|i| i * 2}).to eq [2,4,6]
|
93
|
-
expect(rest).to eq [:fee, "fi", 4]
|
94
|
-
}
|
95
|
-
@double.random_call 5, "hello", [1,2,3], :fee, "fi", 4
|
96
|
-
end
|
97
|
-
|
98
|
-
it "does not eval the block as the return value" do
|
99
|
-
eval_count = 0
|
100
|
-
@double.should_receive(:msg).with {|a| eval_count += 1}
|
101
|
-
@double.msg(:ignore)
|
102
|
-
expect(eval_count).to eq(1)
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
context "handling non-matcher arguments" do
|
107
|
-
it "matches non special symbol (can be removed when deprecated symbols are removed)" do
|
108
|
-
@double.should_receive(:random_call).with(:some_symbol)
|
109
|
-
@double.random_call(:some_symbol)
|
110
|
-
end
|
111
|
-
|
112
|
-
it "matches string against regexp" do
|
113
|
-
@double.should_receive(:random_call).with(/bcd/)
|
114
|
-
@double.random_call("abcde")
|
115
|
-
end
|
116
|
-
|
117
|
-
it "matches regexp against regexp" do
|
118
|
-
@double.should_receive(:random_call).with(/bcd/)
|
119
|
-
@double.random_call(/bcd/)
|
120
|
-
end
|
121
|
-
|
122
|
-
it "matches against a hash submitted and received by value" do
|
123
|
-
@double.should_receive(:random_call).with(:a => "a", :b => "b")
|
124
|
-
@double.random_call(:a => "a", :b => "b")
|
125
|
-
end
|
126
|
-
|
127
|
-
it "matches against a hash submitted by reference and received by value" do
|
128
|
-
opts = {:a => "a", :b => "b"}
|
129
|
-
@double.should_receive(:random_call).with(opts)
|
130
|
-
@double.random_call(:a => "a", :b => "b")
|
131
|
-
end
|
132
|
-
|
133
|
-
it "matches against a hash submitted by value and received by reference" do
|
134
|
-
opts = {:a => "a", :b => "b"}
|
135
|
-
@double.should_receive(:random_call).with(:a => "a", :b => "b")
|
136
|
-
@double.random_call(opts)
|
137
|
-
end
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
@@ -1,116 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'yaml'
|
3
|
-
require 'psych'
|
4
|
-
require 'syck'
|
5
|
-
|
6
|
-
module Spy
|
7
|
-
describe "serialization" do
|
8
|
-
|
9
|
-
class SerializableObject < Struct.new(:foo, :bar); end
|
10
|
-
|
11
|
-
class SerializableMockProxy
|
12
|
-
attr_reader :mock_proxy
|
13
|
-
|
14
|
-
def initialize(mock_proxy)
|
15
|
-
@mock_proxy = mock_proxy
|
16
|
-
end
|
17
|
-
|
18
|
-
def ==(other)
|
19
|
-
other.class == self.class && other.mock_proxy == mock_proxy
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def self.with_yaml_loaded(&block)
|
24
|
-
context 'with YAML loaded' do
|
25
|
-
module_eval(&block)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def self.without_yaml_loaded(&block)
|
30
|
-
context 'without YAML loaded' do
|
31
|
-
before do
|
32
|
-
# We can't really unload yaml, but we can fake it here...
|
33
|
-
@yaml = YAML
|
34
|
-
Object.send(:remove_const, "YAML")
|
35
|
-
Struct.class_eval do
|
36
|
-
alias __old_to_yaml to_yaml
|
37
|
-
undef to_yaml
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
module_eval(&block)
|
42
|
-
|
43
|
-
after do
|
44
|
-
Struct.class_eval do
|
45
|
-
alias to_yaml __old_to_yaml
|
46
|
-
undef __old_to_yaml
|
47
|
-
end
|
48
|
-
|
49
|
-
Object.send(:const_set, "YAML", @yaml)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
let(:serializable_object) { SerializableObject.new(7, "something") }
|
55
|
-
|
56
|
-
def set_spy
|
57
|
-
Spy::Subroutine.new(serializable_object, :bazz).hook(force: true).and_return(5)
|
58
|
-
end
|
59
|
-
|
60
|
-
shared_examples_for 'normal YAML serialization' do
|
61
|
-
it 'serializes to yaml the same with and without stubbing, using #to_yaml' do
|
62
|
-
set_spy
|
63
|
-
expect { Spy.get(serializable_object, :bazz) }.to_not change { serializable_object.to_yaml }
|
64
|
-
end
|
65
|
-
|
66
|
-
it 'serializes to yaml the same with and without stubbing, using YAML.dump' do
|
67
|
-
set_spy
|
68
|
-
expect { Spy.get(serializable_object, :bazz) }.to_not change { ::YAML.dump(serializable_object) }
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
with_yaml_loaded do
|
73
|
-
compiled_with_psych = begin
|
74
|
-
require 'psych'
|
75
|
-
true
|
76
|
-
rescue LoadError
|
77
|
-
false
|
78
|
-
end
|
79
|
-
|
80
|
-
if compiled_with_psych
|
81
|
-
context 'using Syck as the YAML engine' do
|
82
|
-
before(:each) { ::YAML::ENGINE.yamler = 'syck' }
|
83
|
-
it_behaves_like 'normal YAML serialization'
|
84
|
-
end
|
85
|
-
|
86
|
-
context 'using Psych as the YAML engine' do
|
87
|
-
before(:each) { ::YAML::ENGINE.yamler = 'psych' }
|
88
|
-
it_behaves_like 'normal YAML serialization'
|
89
|
-
end
|
90
|
-
else
|
91
|
-
it_behaves_like 'normal YAML serialization'
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
without_yaml_loaded do
|
96
|
-
it 'does not add #to_yaml to the stubbed object' do
|
97
|
-
expect(serializable_object).not_to respond_to(:to_yaml)
|
98
|
-
set_spy
|
99
|
-
expect(serializable_object).not_to respond_to(:to_yaml)
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
it 'marshals the same with and without stubbing' do
|
104
|
-
expect { Spy.get(serializable_object, :bazz) }.to_not change { Marshal.dump(serializable_object) }
|
105
|
-
end
|
106
|
-
|
107
|
-
describe "an object that has its own mock_proxy instance variable" do
|
108
|
-
let(:serializable_object) { SerializableMockProxy.new(:my_mock_proxy) }
|
109
|
-
|
110
|
-
it 'does not interfere with its marshalling' do
|
111
|
-
marshalled_copy = Marshal.load(Marshal.dump(serializable_object))
|
112
|
-
expect(marshalled_copy).to eq serializable_object
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|
data/spec/spy/stash_spec.rb
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module Spy
|
4
|
-
describe "only stashing the original method" do
|
5
|
-
let(:klass) do
|
6
|
-
Class.new do
|
7
|
-
def self.foo(arg)
|
8
|
-
:original_value
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
it "keeps the original method intact after multiple expectations are added on the same method" do
|
14
|
-
spy = Spy.on(klass, :foo)
|
15
|
-
klass.foo(:bazbar)
|
16
|
-
expect(spy).to have_been_called
|
17
|
-
Spy.off(klass, :foo)
|
18
|
-
|
19
|
-
expect(klass.foo(:yeah)).to equal(:original_value)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
describe "when a class method is aliased on a subclass and the method is mocked" do
|
24
|
-
let(:klass) do
|
25
|
-
Class.new do
|
26
|
-
class << self
|
27
|
-
alias alternate_new new
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
it "restores the original aliased public method" do
|
33
|
-
klass = Class.new do
|
34
|
-
class << self
|
35
|
-
alias alternate_new new
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
spy = Spy.on(klass, :alternate_new)
|
40
|
-
expect(klass.alternate_new).to be_nil
|
41
|
-
expect(spy).to have_been_called
|
42
|
-
|
43
|
-
Spy.off(klass, :alternate_new)
|
44
|
-
expect(klass.alternate_new).to be_an_instance_of(klass)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
@@ -1,64 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module Spy
|
4
|
-
describe Subroutine do
|
5
|
-
class Bar
|
6
|
-
def foo(given = nil)
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
let(:obj) { Bar.new }
|
11
|
-
describe "stub implementation" do
|
12
|
-
describe "with no args" do
|
13
|
-
it "execs the block when called" do
|
14
|
-
Subroutine.new(obj, :foo).hook.and_return { :bar }
|
15
|
-
expect(obj.foo).to eq :bar
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
describe "with one arg" do
|
20
|
-
it "execs the block with that arg when called" do
|
21
|
-
Subroutine.new(obj, :foo).hook.and_return {|given| given}
|
22
|
-
expect(obj.foo(:bar)).to eq :bar
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
describe "with variable args" do
|
27
|
-
it "execs the block when called" do
|
28
|
-
Subroutine.new(obj, :foo).hook.and_return {|*given| given.first}
|
29
|
-
expect(obj.foo(:bar)).to eq :bar
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
|
35
|
-
describe "unstub implementation" do
|
36
|
-
it "replaces the stubbed method with the original method" do
|
37
|
-
obj = Object.new
|
38
|
-
def obj.foo; :original; end
|
39
|
-
Subroutine.new(obj, :foo).hook.unhook
|
40
|
-
expect(obj.foo).to eq :original
|
41
|
-
end
|
42
|
-
|
43
|
-
it "restores the correct implementations when stubbed and unstubbed on a parent and child class" do
|
44
|
-
parent = Class.new
|
45
|
-
child = Class.new(parent)
|
46
|
-
|
47
|
-
Spy.on(parent, :new)
|
48
|
-
Spy.on(child, :new)
|
49
|
-
Spy.off(parent, :new)
|
50
|
-
Spy.off(child, :new)
|
51
|
-
|
52
|
-
expect(parent.new).to be_an_instance_of parent
|
53
|
-
expect(child.new).to be_an_instance_of child
|
54
|
-
end
|
55
|
-
|
56
|
-
it "raises a MockExpectationError if the method has not been stubbed" do
|
57
|
-
obj = Object.new
|
58
|
-
expect {
|
59
|
-
Spy.off(obj, :foo)
|
60
|
-
}.to raise_error
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
data/spec/spy/stub_spec.rb
DELETED
@@ -1,79 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module RSpec
|
4
|
-
module Mocks
|
5
|
-
describe "A method stub" do
|
6
|
-
before(:each) do
|
7
|
-
@class = Class.new do
|
8
|
-
class << self
|
9
|
-
def existing_class_method
|
10
|
-
existing_private_class_method
|
11
|
-
end
|
12
|
-
|
13
|
-
private
|
14
|
-
def existing_private_class_method
|
15
|
-
:original_value
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def existing_instance_method
|
20
|
-
existing_private_instance_method
|
21
|
-
end
|
22
|
-
|
23
|
-
private
|
24
|
-
def existing_private_instance_method
|
25
|
-
:original_value
|
26
|
-
end
|
27
|
-
end
|
28
|
-
@instance = @class.new
|
29
|
-
@stub = Object.new
|
30
|
-
end
|
31
|
-
|
32
|
-
describe "using Spy::Subroutine.new" do
|
33
|
-
it "returns declared value when message is received" do
|
34
|
-
Spy::Subroutine.new(@instance, :msg).hook(force: true).and_return(:return_value)
|
35
|
-
expect(@instance.msg).to equal(:return_value)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
it "instructs an instance to respond_to the message" do
|
40
|
-
Spy::Subroutine.new(@instance, :msg).hook(force: true)
|
41
|
-
expect(@instance).to respond_to(:msg)
|
42
|
-
end
|
43
|
-
|
44
|
-
it "instructs a class object to respond_to the message" do
|
45
|
-
Spy::Subroutine.new(@class, :msg).hook(force: true)
|
46
|
-
expect(@class).to respond_to(:msg)
|
47
|
-
end
|
48
|
-
|
49
|
-
it "yields a specified object" do
|
50
|
-
Spy::Subroutine.new(@instance, :method_that_yields).hook(force: true).and_yield(:yielded_obj)
|
51
|
-
current_value = :value_before
|
52
|
-
@instance.method_that_yields {|val| current_value = val}
|
53
|
-
expect(current_value).to eq :yielded_obj
|
54
|
-
end
|
55
|
-
|
56
|
-
it "yields a specified object and return another specified object" do
|
57
|
-
yielded_obj = Spy.double("my mock")
|
58
|
-
Spy::Subroutine.new(yielded_obj, :foo).hook(force: true)
|
59
|
-
Spy::Subroutine.new(@instance, :method_that_yields_and_returns).hook(force: true).and_yield(yielded_obj).and_return(:baz)
|
60
|
-
expect(@instance.method_that_yields_and_returns { |o| o.foo :bar }).to eq :baz
|
61
|
-
end
|
62
|
-
|
63
|
-
it "throws when told to" do
|
64
|
-
Spy::Subroutine.new(@stub, :something).hook(force: true).and_throw(:up)
|
65
|
-
expect { @stub.something }.to throw_symbol(:up)
|
66
|
-
end
|
67
|
-
|
68
|
-
it "throws with argument when told to" do
|
69
|
-
Spy::Subroutine.new(@stub, :something).hook(force: true).and_throw(:up, 'high')
|
70
|
-
expect { @stub.something }.to throw_symbol(:up, 'high')
|
71
|
-
end
|
72
|
-
|
73
|
-
it "overrides a pre-existing method" do
|
74
|
-
Spy::Subroutine.new(@stub, :existing_instance_method).hook(force: true).and_return(:updated_stub_value)
|
75
|
-
expect(@stub.existing_instance_method).to eq :updated_stub_value
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
data/spec/spy/to_ary_spec.rb
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
describe "a double receiving to_ary" do
|
4
|
-
shared_examples "to_ary" do
|
5
|
-
it "returns nil" do
|
6
|
-
expect do
|
7
|
-
expect(obj.to_ary).to be_nil
|
8
|
-
end.to raise_error(NoMethodError)
|
9
|
-
end
|
10
|
-
|
11
|
-
it "doesn't respond" do
|
12
|
-
expect(obj).not_to respond_to(:to_ary)
|
13
|
-
end
|
14
|
-
|
15
|
-
it "can be overridden with a stub" do
|
16
|
-
Spy::Subroutine.new(obj, :to_ary).hook(force: true).and_return(:non_nil_value)
|
17
|
-
expect(obj.to_ary).to be(:non_nil_value)
|
18
|
-
end
|
19
|
-
|
20
|
-
it "responds when overriden" do
|
21
|
-
Spy::Subroutine.new(obj, :to_ary).hook(force: true).and_return(:non_nil_value)
|
22
|
-
expect(obj).to respond_to(:to_ary)
|
23
|
-
end
|
24
|
-
|
25
|
-
it "supports Array#flatten" do
|
26
|
-
obj = Spy.double('foo')
|
27
|
-
expect([obj].flatten).to eq([obj])
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
context "double as_null_object" do
|
32
|
-
let(:obj) { Spy.double('obj').as_null_object }
|
33
|
-
include_examples "to_ary"
|
34
|
-
end
|
35
|
-
|
36
|
-
context "double without as_null_object" do
|
37
|
-
let(:obj) { Spy.double('obj') }
|
38
|
-
include_examples "to_ary"
|
39
|
-
end
|
40
|
-
end
|