surrogate 0.4.3 → 0.5.0
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.
- data/Readme.md +52 -10
- data/lib/surrogate/hatchling.rb +28 -25
- data/lib/surrogate/invocation.rb +17 -0
- data/lib/surrogate/options.rb +2 -2
- data/lib/surrogate/rspec/abstract_failure_message.rb +59 -0
- data/lib/surrogate/rspec/have_been_asked_for_its.rb +78 -0
- data/lib/surrogate/rspec/have_been_initialized_with.rb +12 -0
- data/lib/surrogate/rspec/have_been_told_to.rb +77 -0
- data/lib/surrogate/rspec/invocation_matcher.rb +81 -0
- data/lib/surrogate/rspec/{substitutability_matchers.rb → substitute_for.rb} +0 -0
- data/lib/surrogate/rspec/times_predicate.rb +19 -0
- data/lib/surrogate/rspec/with_filter.rb +123 -0
- data/lib/surrogate/rspec.rb +25 -2
- data/lib/surrogate/values.rb +23 -30
- data/lib/surrogate/version.rb +1 -1
- data/lib/surrogate.rb +1 -0
- data/spec/acceptance_spec.rb +5 -5
- data/spec/defining_api_methods_spec.rb +19 -42
- data/spec/rspec/block_support_spec.rb +129 -0
- data/spec/rspec/messages_spec.rb +13 -10
- data/surrogate.gemspec +1 -1
- metadata +18 -9
- data/lib/surrogate/rspec/api_method_matchers.rb +0 -229
data/lib/surrogate/rspec.rb
CHANGED
@@ -17,9 +17,32 @@ class Surrogate
|
|
17
17
|
@mocks_loaded = bool
|
18
18
|
end
|
19
19
|
end
|
20
|
+
|
21
|
+
module Matchers
|
22
|
+
def have_been_told_to(expected)
|
23
|
+
HaveBeenToldTo.new expected
|
24
|
+
end
|
25
|
+
|
26
|
+
def have_been_asked_for_its(expected)
|
27
|
+
HaveBeenAskedForIts.new expected
|
28
|
+
end
|
29
|
+
|
30
|
+
def have_been_initialized_with(*initialization_args, &block)
|
31
|
+
HaveBeenInitializedWith.new *initialization_args, &block
|
32
|
+
end
|
33
|
+
end
|
20
34
|
end
|
21
35
|
end
|
22
36
|
|
37
|
+
require 'rspec/core'
|
23
38
|
require 'surrogate'
|
24
|
-
require 'surrogate/rspec/
|
25
|
-
|
39
|
+
require 'surrogate/rspec/substitute_for'
|
40
|
+
|
41
|
+
require 'surrogate/rspec/have_been_asked_for_its'
|
42
|
+
require 'surrogate/rspec/have_been_initialized_with'
|
43
|
+
require 'surrogate/rspec/have_been_told_to'
|
44
|
+
|
45
|
+
|
46
|
+
RSpec.configure do |config|
|
47
|
+
config.include Surrogate::RSpec::Matchers
|
48
|
+
end
|
data/lib/surrogate/values.rb
CHANGED
@@ -3,60 +3,53 @@ class Surrogate
|
|
3
3
|
# Superclass for all types of values. Where a value is anything stored
|
4
4
|
# in an instance variable on a surrogate, intended to be returned by an api method
|
5
5
|
class Value
|
6
|
-
|
7
6
|
# convert raw arguments into a value
|
8
7
|
def self.factory(*args, &block)
|
9
8
|
arg = args.first
|
10
|
-
# if arg.kind_of? Exception
|
11
|
-
# Raiseable.new arg
|
12
|
-
# else
|
13
|
-
# MethodQueue.new args
|
14
|
-
# end
|
15
9
|
if args.size > 1
|
16
10
|
ValueQueue.new args
|
17
11
|
elsif arg.kind_of? Exception
|
18
12
|
Raisable.new arg
|
19
|
-
elsif arg.kind_of?
|
13
|
+
elsif arg.kind_of? BaseValue
|
20
14
|
arg
|
21
15
|
else
|
22
|
-
|
16
|
+
BaseValue.new arg
|
23
17
|
end
|
24
18
|
end
|
25
19
|
|
26
|
-
|
27
|
-
@value = value
|
28
|
-
end
|
29
|
-
|
30
|
-
def value(hatchling, method_name)
|
31
|
-
@value
|
32
|
-
end
|
20
|
+
# === the current set of possible values ===
|
33
21
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
end
|
22
|
+
class BaseValue
|
23
|
+
def initialize(value)
|
24
|
+
@value = value
|
25
|
+
end
|
39
26
|
|
27
|
+
def value(method_name)
|
28
|
+
@value
|
29
|
+
end
|
40
30
|
|
41
|
-
|
31
|
+
def factory(*args, &block)
|
32
|
+
Value.factory(*args, &block)
|
33
|
+
end
|
34
|
+
end
|
42
35
|
|
43
|
-
class Surrogate
|
44
|
-
class Value
|
45
36
|
|
46
|
-
class Raisable <
|
37
|
+
class Raisable < BaseValue
|
47
38
|
def value(*)
|
48
39
|
raise @value
|
49
40
|
end
|
50
41
|
end
|
51
42
|
|
52
43
|
|
53
|
-
class ValueQueue <
|
54
|
-
QueueEmpty = Class.new
|
44
|
+
class ValueQueue < BaseValue
|
45
|
+
QueueEmpty = Class.new SurrogateError
|
55
46
|
|
56
|
-
def value(
|
57
|
-
|
58
|
-
|
59
|
-
|
47
|
+
def value(method_name)
|
48
|
+
if empty?
|
49
|
+
raise QueueEmpty
|
50
|
+
else
|
51
|
+
factory(dequeue).value(method_name)
|
52
|
+
end
|
60
53
|
end
|
61
54
|
|
62
55
|
def queue
|
data/lib/surrogate/version.rb
CHANGED
data/lib/surrogate.rb
CHANGED
data/spec/acceptance_spec.rb
CHANGED
@@ -45,11 +45,11 @@ describe Surrogate do
|
|
45
45
|
user_class.find(2).should == :user1
|
46
46
|
|
47
47
|
# set a queue of default values
|
48
|
-
user_class.will_find :user1, :user2, :user3
|
49
|
-
user_class.find(11).should == :user1
|
50
|
-
user_class.find(22).should == :user2
|
51
|
-
user_class.find(33).should == :user3
|
52
|
-
user_class.find
|
48
|
+
user_class.will_find :user1, :user2, :user3 # set three overrides
|
49
|
+
user_class.find(11).should == :user1 # first override
|
50
|
+
user_class.find(22).should == :user2 # second override
|
51
|
+
user_class.find(33).should == :user3 # third override
|
52
|
+
expect { user_class.find 44 }.to raise_error # raise error when nothing left to find
|
53
53
|
# might also be nice to provide a way to raise an error
|
54
54
|
|
55
55
|
# tracking invocations
|
@@ -72,24 +72,13 @@ describe 'define' do
|
|
72
72
|
instance.will_wink(1, 2, 3).should equal instance
|
73
73
|
end
|
74
74
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
end
|
83
|
-
|
84
|
-
specify 'when there is a default block' do
|
85
|
-
mocked_class = Surrogate.endow(Class.new)
|
86
|
-
mocked_class.define(:connect) { :default }
|
87
|
-
mock = mocked_class.new
|
88
|
-
mock.will_connect 1, 2
|
89
|
-
mock.connect.should == 1
|
90
|
-
mock.connect.should == 2
|
91
|
-
mock.connect.should == :default
|
92
|
-
end
|
75
|
+
# Is there something useful the error could say?
|
76
|
+
it 'creates a queue of things to find and raises a QueueEmpty error if there are none left' do
|
77
|
+
mock = mocked_class.new
|
78
|
+
mock.will_wink :quickly, [:slowly]
|
79
|
+
mock.wink.should == :quickly
|
80
|
+
mock.wink.should == [:slowly]
|
81
|
+
expect { mock.wink }.to raise_error Surrogate::Value::ValueQueue::QueueEmpty
|
93
82
|
end
|
94
83
|
end
|
95
84
|
|
@@ -140,24 +129,13 @@ describe 'define' do
|
|
140
129
|
instance.will_have_age(1,2,3).should equal instance
|
141
130
|
end
|
142
131
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
end
|
151
|
-
|
152
|
-
specify 'when there is a default block' do
|
153
|
-
mocked_class = Surrogate.endow(Class.new)
|
154
|
-
mocked_class.define(:name) { 'default' }
|
155
|
-
mock = mocked_class.new
|
156
|
-
mock.will_have_name 'a', 'b'
|
157
|
-
mock.name.should == 'a'
|
158
|
-
mock.name.should == 'b'
|
159
|
-
mock.name.should == 'default'
|
160
|
-
end
|
132
|
+
# Is there something useful the error could say?
|
133
|
+
it 'creates a queue of things to find and raises a QueueEmpty error if there are none left' do
|
134
|
+
mock = mocked_class.new
|
135
|
+
mock.will_have_age 12, 34
|
136
|
+
mock.age.should == 12
|
137
|
+
mock.age.should == 34
|
138
|
+
expect { mock.age }.to raise_error Surrogate::Value::ValueQueue::QueueEmpty
|
161
139
|
end
|
162
140
|
end
|
163
141
|
end
|
@@ -271,12 +249,11 @@ describe 'define' do
|
|
271
249
|
mock = mocked_class.new
|
272
250
|
mock.meth 1
|
273
251
|
mock.meth 1, 2
|
274
|
-
mock.meth [1, 2]
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
]
|
252
|
+
mock.invocations(:meth).should == [Surrogate::Invocation.new([1]), Surrogate::Invocation.new([1, 2])]
|
253
|
+
|
254
|
+
val = 0
|
255
|
+
mock.meth(1, 2) { val = 3 }
|
256
|
+
expect { mock.invocations(:meth).last.block.call }.to change { val }.from(0).to(3)
|
280
257
|
end
|
281
258
|
|
282
259
|
it 'raises an error if asked about invocations for api methods it does not know' do
|
@@ -0,0 +1,129 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
# these all need error messages
|
4
|
+
describe 'RSpec matchers', 'have_been_told_to(...).with { |block| }' do
|
5
|
+
|
6
|
+
let(:dir) { Surrogate.endow(Class.new) { define(:chdir) { nil }}}
|
7
|
+
let(:dir_path) { '/some/dir/path' }
|
8
|
+
|
9
|
+
it 'fails if no submitted_blocks were found' do
|
10
|
+
dir.should_not have_been_told_to(:chdir).with(dir_path) { |block|
|
11
|
+
block.before { raise 'this should not be executed' }
|
12
|
+
}
|
13
|
+
|
14
|
+
dir.chdir dir_path
|
15
|
+
|
16
|
+
dir.should_not have_been_told_to(:chdir).with(dir_path) { |block|
|
17
|
+
block.before { raise 'this should not be executed' }
|
18
|
+
}
|
19
|
+
|
20
|
+
dir.chdir(dir_path) { }
|
21
|
+
dir.should have_been_told_to(:chdir).with(dir_path) { }
|
22
|
+
end
|
23
|
+
|
24
|
+
it "fails if the arguments don't match, even if the block does" do
|
25
|
+
dir.chdir(dir_path) { }
|
26
|
+
dir.should_not have_been_told_to(:chdir).with(dir_path.reverse) { }
|
27
|
+
dir.should have_been_told_to(:chdir).with(dir_path) { }
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'yields a test_block that can make assertions' do
|
31
|
+
dir.chdir(dir_path) { }
|
32
|
+
block_yielded = nil
|
33
|
+
dir.should have_been_told_to(:chdir).with(dir_path) { |block|
|
34
|
+
block_yielded = block
|
35
|
+
}
|
36
|
+
block_yielded.should be
|
37
|
+
end
|
38
|
+
|
39
|
+
describe 'the .returns assertion' do
|
40
|
+
it "passes if the submitted_block does return the value" do
|
41
|
+
dir.chdir(dir_path) { 1 }
|
42
|
+
dir.should_not have_been_told_to(:chdir).with(dir_path) { |block| block.returns 2 }
|
43
|
+
dir.should have_been_told_to(:chdir).with(dir_path) { |block| block.returns 1 }
|
44
|
+
end
|
45
|
+
|
46
|
+
specify "if given a block, it passes the return value to it for making assertions" do
|
47
|
+
dir.chdir(dir_path) { 1 }
|
48
|
+
|
49
|
+
dir.should_not have_been_told_to(:chdir).with(dir_path) { |block|
|
50
|
+
block.returns { |result| result.should == 2 }
|
51
|
+
}
|
52
|
+
|
53
|
+
dir.should have_been_told_to(:chdir).with(dir_path) { |block|
|
54
|
+
block.returns { |result| result.should == 1 }
|
55
|
+
}
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
let(:file) { Surrogate.endow(Class.new) { define(:write) { true }}}
|
61
|
+
let(:file_name) { 'some_file_name.ext' }
|
62
|
+
let(:file_body) { 'some file body' }
|
63
|
+
|
64
|
+
describe 'the .before and .after hooks' do
|
65
|
+
specify "take blocks which it will evaluate before/after invoking the submitted_block" do
|
66
|
+
dir.chdir(dir_path) { file.write file_name, file_body }
|
67
|
+
dir.should have_been_told_to(:chdir).with(dir_path) { |block|
|
68
|
+
block.before { file.should_not have_been_told_to :write }
|
69
|
+
block.after { file.should have_been_told_to :write }
|
70
|
+
}
|
71
|
+
end
|
72
|
+
|
73
|
+
example "multiple invocations wrong number of times" do
|
74
|
+
dir.chdir(dir_path) { file.write file_name, file_body }
|
75
|
+
dir.chdir(dir_path) { file.write file_name, file_body }
|
76
|
+
dir.should_not have_been_told_to(:chdir).times(1).with(dir_path) { |block|
|
77
|
+
block.before { file.should_not have_been_told_to :write }
|
78
|
+
block.after { file.should have_been_told_to :write }
|
79
|
+
}
|
80
|
+
end
|
81
|
+
|
82
|
+
example "multiple invocations correct number of times" do
|
83
|
+
dir.chdir(dir_path) { file.write file_name, file_body }
|
84
|
+
dir.chdir(dir_path) { file.write file_name, file_body }
|
85
|
+
dir.should have_been_told_to(:chdir).times(2).with(dir_path) { |block|
|
86
|
+
block.before { file.should_not have_been_told_to :write }
|
87
|
+
block.after { file.should have_been_told_to :write }
|
88
|
+
}
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe 'the .arity assertion' do
|
93
|
+
it "takes a number corresponding to the arity of the block" do
|
94
|
+
klass = Surrogate.endow(Class.new)
|
95
|
+
klass.define(:meth) { self }
|
96
|
+
klass.new.meth { |a| }.should have_been_told_to(:meth).with { |b| b.arity 1 }
|
97
|
+
klass.new.meth { |a,b| }.should have_been_told_to(:meth).with { |b| b.arity 2 }
|
98
|
+
klass.new.meth { |a,b,c| }.should have_been_told_to(:meth).with { |b| b.arity 3 }
|
99
|
+
klass.new.meth { |*a| }.should have_been_told_to(:meth).with { |b| b.arity -1 }
|
100
|
+
expect {
|
101
|
+
klass.new.meth { |a| }.should have_been_told_to(:meth).with { |b| b.arity 123 }
|
102
|
+
}.to raise_error RSpec::Expectations::ExpectationNotMetError
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe ".call_with" do
|
107
|
+
it 'allows the user to provide arguments' do
|
108
|
+
klass = Surrogate.endow(Class.new).define(:add) { self }
|
109
|
+
instance = klass.new
|
110
|
+
instance.add { |a, b, &c| a + b + c.call }
|
111
|
+
instance.should have_been_told_to(:add).with { |block|
|
112
|
+
block.call_with(1, 2) { 3 }
|
113
|
+
block.returns 6
|
114
|
+
}
|
115
|
+
|
116
|
+
instance = klass.new
|
117
|
+
i = 10
|
118
|
+
instance.add { |n, &b| i += n + b.call }
|
119
|
+
instance.should have_been_told_to(:add).with { |block|
|
120
|
+
block.call_with(3) { 4 }
|
121
|
+
block.after { i.should == 17 }
|
122
|
+
}
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
describe ".raising is like RSpec's raise_error interface" do
|
127
|
+
it { pending 'IDK what I want this to be like yet' }
|
128
|
+
end
|
129
|
+
end
|
data/spec/rspec/messages_spec.rb
CHANGED
@@ -1,34 +1,37 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
messages_for = Surrogate::RSpec::MessagesFor
|
4
3
|
|
5
|
-
describe
|
4
|
+
describe Surrogate::RSpec::AbstractFailureMessage::ArgsInspector, 'argument inspection' do
|
6
5
|
|
7
6
|
describe 'individual argument inspection inspection' do
|
8
7
|
it 'inspects non RSpec matchers as their default inspection' do
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
described_class.inspect_argument("1").should == '"1"'
|
9
|
+
described_class.inspect_argument(1).should == "1"
|
10
|
+
described_class.inspect_argument([/a/]).should == "[/a/]"
|
12
11
|
end
|
13
12
|
|
14
13
|
it 'inspects rspec matchers' do
|
15
|
-
|
16
|
-
|
14
|
+
described_class.inspect_argument(no_args).should == 'no args'
|
15
|
+
described_class.inspect_argument(hash_including abc: 123).should == 'hash_including(:abc=>123)'
|
17
16
|
end
|
18
17
|
end
|
19
18
|
|
20
19
|
|
21
20
|
describe 'multiple argument inspection' do
|
21
|
+
def inspect_args(args)
|
22
|
+
described_class.inspect Surrogate::Invocation.new(args)
|
23
|
+
end
|
24
|
+
|
22
25
|
it "wraps individual arguments in `'" do
|
23
|
-
|
26
|
+
inspect_args([/a/]).should == "`/a/'"
|
24
27
|
end
|
25
28
|
|
26
29
|
it "joins arguments with commas" do
|
27
|
-
|
30
|
+
inspect_args(['x', no_args]).should == "`\"x\", no args'"
|
28
31
|
end
|
29
32
|
|
30
33
|
it 'returns no_args when the array is empty' do
|
31
|
-
|
34
|
+
inspect_args([]).should == "`no args'"
|
32
35
|
end
|
33
36
|
end
|
34
37
|
end
|
data/surrogate.gemspec
CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
|
21
|
-
s.add_runtime_dependency 'bindable_block', '= 0.0.
|
21
|
+
s.add_runtime_dependency 'bindable_block', '= 0.0.5.1'
|
22
22
|
|
23
23
|
s.add_development_dependency "rspec", '~> 2.8.0' # TODO: Figure out how far back we can work with
|
24
24
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: surrogate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,22 +9,22 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-06-
|
12
|
+
date: 2012-06-20 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bindable_block
|
16
|
-
requirement: &
|
16
|
+
requirement: &70339421986340 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - =
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 0.0.
|
21
|
+
version: 0.0.5.1
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70339421986340
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rspec
|
27
|
-
requirement: &
|
27
|
+
requirement: &70339421985140 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,7 +32,7 @@ dependencies:
|
|
32
32
|
version: 2.8.0
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70339421985140
|
36
36
|
description: Framework to aid in handrolling mock/spy objects.
|
37
37
|
email:
|
38
38
|
- josh.cheek@gmail.com
|
@@ -50,14 +50,22 @@ files:
|
|
50
50
|
- lib/surrogate/endower.rb
|
51
51
|
- lib/surrogate/hatchery.rb
|
52
52
|
- lib/surrogate/hatchling.rb
|
53
|
+
- lib/surrogate/invocation.rb
|
53
54
|
- lib/surrogate/options.rb
|
54
55
|
- lib/surrogate/rspec.rb
|
55
|
-
- lib/surrogate/rspec/
|
56
|
-
- lib/surrogate/rspec/
|
56
|
+
- lib/surrogate/rspec/abstract_failure_message.rb
|
57
|
+
- lib/surrogate/rspec/have_been_asked_for_its.rb
|
58
|
+
- lib/surrogate/rspec/have_been_initialized_with.rb
|
59
|
+
- lib/surrogate/rspec/have_been_told_to.rb
|
60
|
+
- lib/surrogate/rspec/invocation_matcher.rb
|
61
|
+
- lib/surrogate/rspec/substitute_for.rb
|
62
|
+
- lib/surrogate/rspec/times_predicate.rb
|
63
|
+
- lib/surrogate/rspec/with_filter.rb
|
57
64
|
- lib/surrogate/values.rb
|
58
65
|
- lib/surrogate/version.rb
|
59
66
|
- spec/acceptance_spec.rb
|
60
67
|
- spec/defining_api_methods_spec.rb
|
68
|
+
- spec/rspec/block_support_spec.rb
|
61
69
|
- spec/rspec/have_been_asked_for_its_spec.rb
|
62
70
|
- spec/rspec/have_been_initialized_with_spec.rb
|
63
71
|
- spec/rspec/have_been_told_to_spec.rb
|
@@ -94,6 +102,7 @@ summary: Framework to aid in handrolling mock/spy objects.
|
|
94
102
|
test_files:
|
95
103
|
- spec/acceptance_spec.rb
|
96
104
|
- spec/defining_api_methods_spec.rb
|
105
|
+
- spec/rspec/block_support_spec.rb
|
97
106
|
- spec/rspec/have_been_asked_for_its_spec.rb
|
98
107
|
- spec/rspec/have_been_initialized_with_spec.rb
|
99
108
|
- spec/rspec/have_been_told_to_spec.rb
|