aidmock 0.1.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/.gitignore +2 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +28 -0
- data/README.textile +5 -0
- data/Rakefile +51 -0
- data/VERSION +1 -0
- data/aidmock.gemspec +71 -0
- data/examples/mock_spec.rb +50 -0
- data/lib/aidmock/basic_object.rb +25 -0
- data/lib/aidmock/errors.rb +7 -0
- data/lib/aidmock/frameworks/rspec.rb +158 -0
- data/lib/aidmock/frameworks.rb +27 -0
- data/lib/aidmock/interface.rb +57 -0
- data/lib/aidmock/matchers.rb +181 -0
- data/lib/aidmock/method_descriptor.rb +136 -0
- data/lib/aidmock/sanity.rb +79 -0
- data/lib/aidmock/void_class.rb +27 -0
- data/lib/aidmock.rb +105 -0
- data/spec/aidmock/frameworks/rspec_spec.rb +212 -0
- data/spec/aidmock/interface_spec.rb +66 -0
- data/spec/aidmock/matchers_spec.rb +237 -0
- data/spec/aidmock/method_descriptor_spec.rb +205 -0
- data/spec/aidmock/sanity_spec.rb +119 -0
- data/spec/aidmock_spec.rb +124 -0
- data/spec/spec_helper.rb +57 -0
- metadata +95 -0
@@ -0,0 +1,237 @@
|
|
1
|
+
# Copyright (c) 2011 Wilker Lúcio
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
20
|
+
|
21
|
+
describe Aidmock::Matchers do
|
22
|
+
m = ::Aidmock::Matchers
|
23
|
+
|
24
|
+
trueMatch = Class.new do
|
25
|
+
def match?(obj)
|
26
|
+
true
|
27
|
+
end
|
28
|
+
end.new
|
29
|
+
|
30
|
+
falseMatch = Class.new do
|
31
|
+
def match?(obj)
|
32
|
+
false
|
33
|
+
end
|
34
|
+
end.new
|
35
|
+
|
36
|
+
context "create matcher by value" do
|
37
|
+
it "use the matcher if one is sent" do
|
38
|
+
m.create(trueMatch).should == trueMatch
|
39
|
+
end
|
40
|
+
|
41
|
+
it "use an AnyMatcher if an array is sent" do
|
42
|
+
m.create([trueMatch, falseMatch]).should be_an_instance_of(m::AnyMatcher)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "use KindOfMatcher if a class is sent" do
|
46
|
+
m.create(String).should be_an_instance_of(m::KindOfMatcher)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "use AnythingMatcher if nil is sent" do
|
50
|
+
m.create(nil).should be_an_instance_of(m::AnythingMatcher)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "use DuckTypeMatcher if receive a symbol" do
|
54
|
+
m.create(:to_s).should be_an_instance_of(m::DuckTypeMatcher)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "use HashMatcher if receive a hash" do
|
58
|
+
m.create(:name => nil).should be_an_instance_of(m::HashMatcher)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "raise error if can't figure a matcher" do
|
62
|
+
expect { m.create("") }.to raise_error
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context "matchers" do
|
67
|
+
context "AnyMatcher" do
|
68
|
+
it "pass if any of matchers matches" do
|
69
|
+
matcher = m::AnyMatcher.new(falseMatch, trueMatch)
|
70
|
+
matcher.should matches("obj")
|
71
|
+
end
|
72
|
+
|
73
|
+
it "fails if no matcher can match" do
|
74
|
+
matcher = m::AnyMatcher.new(falseMatch, falseMatch)
|
75
|
+
matcher.should_not matches("obj")
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context "AnythingMatcher" do
|
80
|
+
it "always pass" do
|
81
|
+
matcher = m::AnythingMatcher.new
|
82
|
+
matcher.should matches("something")
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should pass with nil" do
|
86
|
+
matcher = m::AnythingMatcher.new
|
87
|
+
matcher.should matches(nil)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context "DuckTypeMatcher" do
|
92
|
+
it "pass if object respond to all methods" do
|
93
|
+
matcher = m::DuckTypeMatcher.new(:to_s, :gsub)
|
94
|
+
matcher.should matches("string")
|
95
|
+
end
|
96
|
+
|
97
|
+
it "pass if object is nil" do
|
98
|
+
matcher = m::DuckTypeMatcher.new(:to_s, :gsub)
|
99
|
+
matcher.should matches(nil)
|
100
|
+
end
|
101
|
+
|
102
|
+
it "fail if object don't respond to any of methods" do
|
103
|
+
matcher = m::DuckTypeMatcher.new(:to_s, :gsub, :i_fail_things)
|
104
|
+
matcher.should_not matches("string")
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context "InstanceOfMatcher" do
|
109
|
+
it "pass if the object is an instance of given" do
|
110
|
+
matcher = m::InstanceOfMatcher.new(String)
|
111
|
+
matcher.should matches("string")
|
112
|
+
end
|
113
|
+
|
114
|
+
it "pass if the object is nil" do
|
115
|
+
matcher = m::InstanceOfMatcher.new(String)
|
116
|
+
matcher.should matches(nil)
|
117
|
+
end
|
118
|
+
|
119
|
+
it "fail if object is not an instance of given" do
|
120
|
+
matcher = m::InstanceOfMatcher.new(Numeric)
|
121
|
+
matcher.should_not matches(4)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
context "KindOfMatcher" do
|
126
|
+
it "pass if the object is an instance of given" do
|
127
|
+
matcher = m::KindOfMatcher.new(String)
|
128
|
+
matcher.should matches("string")
|
129
|
+
end
|
130
|
+
|
131
|
+
it "pass if the object is an kind of given" do
|
132
|
+
matcher = m::KindOfMatcher.new(Numeric)
|
133
|
+
matcher.should matches(4)
|
134
|
+
end
|
135
|
+
|
136
|
+
it "pass if the object is nil" do
|
137
|
+
matcher = m::KindOfMatcher.new(String)
|
138
|
+
matcher.should matches(nil)
|
139
|
+
end
|
140
|
+
|
141
|
+
it "fail if object is not an instance of given" do
|
142
|
+
matcher = m::KindOfMatcher.new(String)
|
143
|
+
matcher.should_not matches(4)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
context "HashMatcher" do
|
148
|
+
context "flexible mode" do
|
149
|
+
it "pass if hash contains only valid keys" do
|
150
|
+
matcher = m::HashMatcher.new(:name => trueMatch, :email => falseMatch)
|
151
|
+
matcher.should matches(:name => "hi")
|
152
|
+
end
|
153
|
+
|
154
|
+
it "pass if the object is nil" do
|
155
|
+
matcher = m::HashMatcher.new(:name => trueMatch, :email => falseMatch)
|
156
|
+
matcher.should matches(nil)
|
157
|
+
end
|
158
|
+
|
159
|
+
it "fails if send an invalid key to hash" do
|
160
|
+
matcher = m::HashMatcher.new(:name => trueMatch, :email => trueMatch)
|
161
|
+
matcher.should_not matches(:other => "hi")
|
162
|
+
end
|
163
|
+
|
164
|
+
it "fails if send a valid key with invalid value" do
|
165
|
+
matcher = m::HashMatcher.new(:name => falseMatch, :email => trueMatch)
|
166
|
+
matcher.should_not matches(:name => "bar")
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
context "strict mode" do
|
171
|
+
it "pass if hash contains all valid keys" do
|
172
|
+
matcher = m::HashMatcher.new({:name => trueMatch, :email => trueMatch}, true)
|
173
|
+
matcher.should matches(:name => "hi", :email => "ho")
|
174
|
+
end
|
175
|
+
|
176
|
+
it "fails if any key is missing" do
|
177
|
+
matcher = m::HashMatcher.new({:name => trueMatch, :email => trueMatch}, true)
|
178
|
+
matcher.should_not matches(:name => "hi")
|
179
|
+
end
|
180
|
+
|
181
|
+
it "fails if has extra keys" do
|
182
|
+
matcher = m::HashMatcher.new({:name => trueMatch, :email => trueMatch}, true)
|
183
|
+
matcher.should_not matches(:name => "hi", :email => "ho", :other => "hu")
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
context "NotNilArgMatcher" do
|
189
|
+
it "pass if internal matcher pass" do
|
190
|
+
matcher = m::NotNilArgMatcher.new(trueMatch)
|
191
|
+
matcher.should matches("hi")
|
192
|
+
end
|
193
|
+
|
194
|
+
it "fails if internal matcher fails" do
|
195
|
+
matcher = m::NotNilArgMatcher.new(falseMatch)
|
196
|
+
matcher.should_not matches("hi")
|
197
|
+
end
|
198
|
+
|
199
|
+
it "fails if object is nil" do
|
200
|
+
matcher = m::NotNilArgMatcher.new(trueMatch)
|
201
|
+
matcher.should_not matches(nil)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
context "OptionalArgMatcher" do
|
206
|
+
it "just call match at given matcher" do
|
207
|
+
matcher = m::OptionalArgMatcher.new(trueMatch)
|
208
|
+
matcher.should matches("thing")
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
context "SplatArgMatcher" do
|
213
|
+
it "use anything matcher by default" do
|
214
|
+
matcher = m::SplatArgMatcher.new
|
215
|
+
matcher.should matches([true])
|
216
|
+
end
|
217
|
+
|
218
|
+
it "should try to match every given value at splat" do
|
219
|
+
matcher = m::SplatArgMatcher.new(trueMatch)
|
220
|
+
trueMatch.should_receive(:match?).with(1) { true }
|
221
|
+
trueMatch.should_receive(:match?).with(2) { true }
|
222
|
+
trueMatch.should_receive(:match?).with(3) { true }
|
223
|
+
|
224
|
+
matcher.should matches([1, 2, 3])
|
225
|
+
end
|
226
|
+
|
227
|
+
it "fail if any of args don't respect matcher" do
|
228
|
+
matcher = m::SplatArgMatcher.new(trueMatch)
|
229
|
+
trueMatch.stub(:match?).with(1) { true }
|
230
|
+
trueMatch.stub(:match?).with(2) { false }
|
231
|
+
trueMatch.stub(:match?).with(3) { true }
|
232
|
+
|
233
|
+
matcher.should_not matches([1, 2, 3])
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
@@ -0,0 +1,205 @@
|
|
1
|
+
# Copyright (c) 2011 Wilker Lúcio
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
20
|
+
|
21
|
+
describe Aidmock::MethodDescriptor do
|
22
|
+
mock_descriptor = Aidmock::Frameworks::MockDescriptor
|
23
|
+
md = Aidmock::MethodDescriptor
|
24
|
+
m = Aidmock::Matchers
|
25
|
+
|
26
|
+
trueMatch = Class.new do
|
27
|
+
def match?(obj)
|
28
|
+
true
|
29
|
+
end
|
30
|
+
end.new
|
31
|
+
|
32
|
+
falseMatch = Class.new do
|
33
|
+
def match?(obj)
|
34
|
+
false
|
35
|
+
end
|
36
|
+
end.new
|
37
|
+
|
38
|
+
def mock_return(val)
|
39
|
+
Aidmock::Frameworks::MockDescriptor.new(nil, :some, val)
|
40
|
+
end
|
41
|
+
|
42
|
+
def mock_args(args)
|
43
|
+
Aidmock::Frameworks::MockDescriptor.new(nil, :some, nil, args)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "verify the arguments and return value" do
|
47
|
+
double = mock_descriptor.new(nil, :method, :result, [:args])
|
48
|
+
desc = md.new(:some, nil)
|
49
|
+
desc.should_receive(:verify_arguments).with(double)
|
50
|
+
desc.should_receive(:verify_return).with(double)
|
51
|
+
desc.verify(double)
|
52
|
+
end
|
53
|
+
|
54
|
+
context "verifying return value" do
|
55
|
+
it "raise error if return value don't match" do
|
56
|
+
desc = md.new(:some, falseMatch)
|
57
|
+
|
58
|
+
expect { desc.verify_return(mock_return([nil])) }.to raise_error(Aidmock::MethodInterfaceReturnNotMatchError)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "not raise error if return value match" do
|
62
|
+
desc = md.new(:some, trueMatch)
|
63
|
+
|
64
|
+
expect { desc.verify_return(mock_return([nil])) }.to_not raise_error
|
65
|
+
end
|
66
|
+
|
67
|
+
it "send double value to matcher" do
|
68
|
+
desc = md.new(:some, trueMatch)
|
69
|
+
trueMatch.should_receive(:match?).with("hi").and_return(true)
|
70
|
+
trueMatch.should_receive(:match?).with("ho").and_return(true)
|
71
|
+
|
72
|
+
desc.verify_return(mock_return(["hi", "ho"]))
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context "verifying arguments" do
|
77
|
+
context "testing arguments arity" do
|
78
|
+
context "on fixed arguments length" do
|
79
|
+
it "raise error if user send less arguments than method expects" do
|
80
|
+
desc = md.new(:some, nil, trueMatch, trueMatch)
|
81
|
+
|
82
|
+
expect { desc.verify_arguments(mock_args([5]))}.to raise_error(Aidmock::MethodInterfaceArgumentsNotMatchError, "error on mock method :some, expected 2 arguments, 1 sent")
|
83
|
+
end
|
84
|
+
|
85
|
+
it "raise error if user send more arguments than method expects" do
|
86
|
+
desc = md.new(:some, nil, trueMatch, trueMatch)
|
87
|
+
|
88
|
+
expect { desc.verify_arguments(mock_args([5, 6, 7]))}.to raise_error(Aidmock::MethodInterfaceArgumentsNotMatchError, "error on mock method :some, expected 2 arguments, 3 sent")
|
89
|
+
end
|
90
|
+
|
91
|
+
it "not raise error if they are in correct arity" do
|
92
|
+
desc = md.new(:some, nil, trueMatch, trueMatch)
|
93
|
+
|
94
|
+
expect { desc.verify_arguments(mock_args([5, 6]))}.to_not raise_error
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context "on variable arguments length" do
|
99
|
+
it "raise error if number of arguments is less than required ones" do
|
100
|
+
desc = md.new(:some, nil, trueMatch, Aidmock::Matchers::OptionalArgMatcher.new(trueMatch))
|
101
|
+
|
102
|
+
expect { desc.verify_arguments(mock_args([])) }.to raise_error(Aidmock::MethodInterfaceArgumentsNotMatchError, "error on mock method :some, expected at least 1, 0 sent")
|
103
|
+
end
|
104
|
+
|
105
|
+
it "raise error if it has more args than possible (after optional ones)" do
|
106
|
+
desc = md.new(:some, nil, trueMatch, Aidmock::Matchers::OptionalArgMatcher.new(trueMatch))
|
107
|
+
|
108
|
+
expect { desc.verify_arguments(mock_args([1, 2, 3])) }.to raise_error(Aidmock::MethodInterfaceArgumentsNotMatchError, "error on mock method :some, expected at most 2, 3 sent")
|
109
|
+
end
|
110
|
+
|
111
|
+
it "dont raise error if fits on argument length" do
|
112
|
+
desc = md.new(:some, nil, trueMatch, Aidmock::Matchers::OptionalArgMatcher.new(trueMatch))
|
113
|
+
|
114
|
+
expect { desc.verify_arguments(mock_args([1])) }.to_not raise_error
|
115
|
+
expect { desc.verify_arguments(mock_args([1, 2])) }.to_not raise_error
|
116
|
+
end
|
117
|
+
|
118
|
+
it "dont raise error if has more arguments than max, but has a splat" do
|
119
|
+
desc = md.new(:some, nil, trueMatch, Aidmock::Matchers::SplatArgMatcher.new(trueMatch))
|
120
|
+
|
121
|
+
expect { desc.verify_arguments(mock_args([1, 2, 3])) }.to_not raise_error
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
context "checking arguments" do
|
127
|
+
it "try each argument on respective matcher" do
|
128
|
+
m1 = mock
|
129
|
+
m2 = mock
|
130
|
+
|
131
|
+
m1.should_receive(:match?).with(1).and_return(true)
|
132
|
+
m2.should_receive(:match?).with(2).and_return(true)
|
133
|
+
|
134
|
+
desc = md.new(:some, nil, m1, m2)
|
135
|
+
desc.verify_arguments(mock_args([1, 2]))
|
136
|
+
end
|
137
|
+
|
138
|
+
it "raise error if any matcher fail" do
|
139
|
+
desc = md.new(:some, nil, falseMatch, trueMatch)
|
140
|
+
|
141
|
+
expect { desc.verify_arguments(mock_args([1, 2])) }.to raise_error(Aidmock::MethodInterfaceArgumentsNotMatchError)
|
142
|
+
end
|
143
|
+
|
144
|
+
it "send an array with others if has a splat" do
|
145
|
+
matcher = mock
|
146
|
+
matcher.should_receive(:match?).with(2).and_return(true)
|
147
|
+
matcher.should_receive(:match?).with(3).and_return(true)
|
148
|
+
|
149
|
+
desc = md.new(:some, nil, trueMatch, Aidmock::Matchers::SplatArgMatcher.new(matcher))
|
150
|
+
desc.verify_arguments(mock_args([1, 2, 3]))
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
context "#arity" do
|
156
|
+
it "return 0 if no arguments are given" do
|
157
|
+
md.new(:some, nil).arity.should == 0
|
158
|
+
end
|
159
|
+
|
160
|
+
it "return positive number of arguments if they are regular ones" do
|
161
|
+
md.new(:some, nil, nil, nil).arity.should == 2
|
162
|
+
end
|
163
|
+
|
164
|
+
it "return -1 if start with optional argument" do
|
165
|
+
md.new(:some, nil, m::OptionalArgMatcher.new(nil)).arity.should == -1
|
166
|
+
end
|
167
|
+
|
168
|
+
it "return -1 if start with splat argument" do
|
169
|
+
md.new(:some, nil, m::SplatArgMatcher.new(nil)).arity.should == -1
|
170
|
+
end
|
171
|
+
|
172
|
+
it "return negative value when has both optional and required args" do
|
173
|
+
md.new(:some, nil, nil, m::OptionalArgMatcher.new(nil)).arity.should == -2
|
174
|
+
end
|
175
|
+
|
176
|
+
it "return negative value when has both splt and required args" do
|
177
|
+
md.new(:some, nil, nil, m::SplatArgMatcher.new(nil)).arity.should == -2
|
178
|
+
end
|
179
|
+
|
180
|
+
it "return negative when have optional, required and splt args" do
|
181
|
+
md.new(:some, nil, nil, m::OptionalArgMatcher.new(nil), m::SplatArgMatcher.new(nil)).arity.should == -2
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
context "#required_arity" do
|
186
|
+
before :each do
|
187
|
+
@m = md.new(:some, nil)
|
188
|
+
end
|
189
|
+
|
190
|
+
it "return arity if its positive" do
|
191
|
+
@m.stub(:arity).and_return(1)
|
192
|
+
@m.required_arity.should == 1
|
193
|
+
end
|
194
|
+
|
195
|
+
it "return 0 if arity is 0" do
|
196
|
+
@m.stub(:arity).and_return(0)
|
197
|
+
@m.required_arity.should == 0
|
198
|
+
end
|
199
|
+
|
200
|
+
it "return arity positive less 1 if it's negative" do
|
201
|
+
@m.stub(:arity).and_return(-2)
|
202
|
+
@m.required_arity.should == 1
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
# Copyright (c) 2011 Wilker Lúcio
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
20
|
+
|
21
|
+
describe Aidmock::Sanity do
|
22
|
+
context ".sanitize_interfaces" do
|
23
|
+
it "check each defined interface" do
|
24
|
+
m1 = mock
|
25
|
+
m2 = mock
|
26
|
+
|
27
|
+
Aidmock.stub!(:interfaces).and_return({:a => m1, :b => m2})
|
28
|
+
Aidmock::Sanity.should_receive(:sanitize_interface).with(m1)
|
29
|
+
Aidmock::Sanity.should_receive(:sanitize_interface).with(m2)
|
30
|
+
|
31
|
+
Aidmock::Sanity.sanitize_interfaces
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context ".sanitize_interface" do
|
36
|
+
it "check each method defined on interface" do
|
37
|
+
m1 = mock
|
38
|
+
m2 = mock
|
39
|
+
m3 = mock
|
40
|
+
m4 = mock
|
41
|
+
ca = mock
|
42
|
+
|
43
|
+
interface = Aidmock::Interface.allocate
|
44
|
+
interface.stub(:methods).and_return([m1, m2])
|
45
|
+
interface.stub(:class_methods).and_return([m3, m4])
|
46
|
+
interface.stub(:klass).and_return(ca)
|
47
|
+
|
48
|
+
Aidmock::Sanity.should_receive(:sanitize_method).with(ca, m1)
|
49
|
+
Aidmock::Sanity.should_receive(:sanitize_method).with(ca, m2)
|
50
|
+
Aidmock::Sanity.should_receive(:sanitize_method).with(ca, m3)
|
51
|
+
Aidmock::Sanity.should_receive(:sanitize_method).with(ca, m4)
|
52
|
+
|
53
|
+
Aidmock::Sanity.sanitize_interface(interface)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context ".sanitize_method" do
|
58
|
+
before :each do
|
59
|
+
@ca = mock(:allocate => Object)
|
60
|
+
@me = mock(:name => :to_s, :arity => 0, :class_method? => false)
|
61
|
+
end
|
62
|
+
|
63
|
+
it "verify if method is defined" do
|
64
|
+
Aidmock::Sanity.should_receive(:verify_method_defined).with(@ca, @me)
|
65
|
+
Aidmock::Sanity.sanitize_method(@ca, @me)
|
66
|
+
end
|
67
|
+
|
68
|
+
it "verify if method arity" do
|
69
|
+
Aidmock::Sanity.should_receive(:verify_method_arity).with(@ca, @me)
|
70
|
+
Aidmock::Sanity.sanitize_method(@ca, @me)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context ".verify_method_defined" do
|
75
|
+
it "raise error if object don't have the method defined" do
|
76
|
+
klass = Object
|
77
|
+
method = Aidmock::MethodDescriptor.new(:foo_isnt_here, nil)
|
78
|
+
|
79
|
+
expect { Aidmock::Sanity.verify_method_defined(klass, method) }.to raise_error("Aidmock Sanity: method 'foo_isnt_here' is not defined for Object")
|
80
|
+
end
|
81
|
+
|
82
|
+
it "don't raise error if object has the method" do
|
83
|
+
klass = Object
|
84
|
+
method = Aidmock::MethodDescriptor.new(:to_s, nil)
|
85
|
+
|
86
|
+
expect { Aidmock::Sanity.verify_method_defined(klass, method) }.to_not raise_error
|
87
|
+
end
|
88
|
+
|
89
|
+
it "don't check for regexp methods" do
|
90
|
+
klass = String
|
91
|
+
method = Aidmock::MethodDescriptor.new(/concat_.*/, nil, [String, Fixnum])
|
92
|
+
|
93
|
+
expect { Aidmock::Sanity.verify_method_arity(klass, method) }.to_not raise_error
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context ".verify_method_arity" do
|
98
|
+
it "raise error if arity is different" do
|
99
|
+
klass = String
|
100
|
+
method = Aidmock::MethodDescriptor.new(:gsub, nil)
|
101
|
+
|
102
|
+
expect { Aidmock::Sanity.verify_method_arity(klass, method) }.to raise_error("Aidmock Sanity: method 'gsub' of String mismatch interface arity, -1 for 0")
|
103
|
+
end
|
104
|
+
|
105
|
+
it "not raise error if arity is same" do
|
106
|
+
klass = String
|
107
|
+
method = Aidmock::MethodDescriptor.new(:concat, nil, [String, Fixnum])
|
108
|
+
|
109
|
+
expect { Aidmock::Sanity.verify_method_arity(klass, method) }.to_not raise_error
|
110
|
+
end
|
111
|
+
|
112
|
+
it "don't check for regexp methods" do
|
113
|
+
klass = String
|
114
|
+
method = Aidmock::MethodDescriptor.new(/concat_.*/, nil, [String, Fixnum])
|
115
|
+
|
116
|
+
expect { Aidmock::Sanity.verify_method_arity(klass, method) }.to_not raise_error
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
# Copyright (c) 2011 Wilker Lúcio
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
20
|
+
|
21
|
+
describe Aidmock do
|
22
|
+
context ".interface" do
|
23
|
+
end
|
24
|
+
|
25
|
+
context ".stub" do
|
26
|
+
end
|
27
|
+
|
28
|
+
context ".verify" do
|
29
|
+
it "do verify double on each double returned by framework" do
|
30
|
+
m1 = mock; m2 = mock; m3 = mock
|
31
|
+
framework = stub(:mocks => [m1, m2, m3])
|
32
|
+
Aidmock.stub!(:framework) { framework }
|
33
|
+
|
34
|
+
Aidmock.should_receive(:verify_double).with(m1) { nil }
|
35
|
+
Aidmock.should_receive(:verify_double).with(m2) { nil }
|
36
|
+
Aidmock.should_receive(:verify_double).with(m3) { nil }
|
37
|
+
|
38
|
+
Aidmock.verify
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context ".verify_double" do
|
43
|
+
it "call to verify chain if the chain has any element" do
|
44
|
+
double = Aidmock::Frameworks::MockDescriptor.new("object", :to_s, nil, [])
|
45
|
+
|
46
|
+
Aidmock.stub!(:chain_for).with(String) { [String] }
|
47
|
+
Aidmock.should_receive(:verify_double_on_chain).with(double, [String])
|
48
|
+
|
49
|
+
Aidmock.send :verify_double, double
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context ".verify_double_on_chain" do
|
54
|
+
it "call verify on method descriptor if method exists" do
|
55
|
+
double = mock
|
56
|
+
chain = mock
|
57
|
+
method = mock
|
58
|
+
method.should_receive(:verify).with(double)
|
59
|
+
|
60
|
+
Aidmock.stub!(:find_method_on_chain).with(double, chain).and_return(method)
|
61
|
+
|
62
|
+
Aidmock.send(:verify_double_on_chain, double, chain)
|
63
|
+
end
|
64
|
+
|
65
|
+
it "raise error if method can't be found" do
|
66
|
+
double = stub(:method => nil, :object => nil)
|
67
|
+
chain = mock
|
68
|
+
|
69
|
+
Aidmock.stub!(:find_method_on_chain).with(double, chain).and_return(nil)
|
70
|
+
|
71
|
+
expect { Aidmock.send(:verify_double_on_chain, double, chain) }.to raise_error(Aidmock::MethodInterfaceNotDefinedError)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context ".find_method_on_chain" do
|
76
|
+
it "get method if the interface has it" do
|
77
|
+
double = stub(:method => :some)
|
78
|
+
interface = stub
|
79
|
+
interface.stub(:find_method).with(double).and_return(true)
|
80
|
+
|
81
|
+
Aidmock.send(:find_method_on_chain, double, [interface]).should == true
|
82
|
+
end
|
83
|
+
|
84
|
+
it "return nil if no interface has the method" do
|
85
|
+
double = stub(:method => :some)
|
86
|
+
interface = stub
|
87
|
+
interface.stub(:find_method).with(double) { nil }
|
88
|
+
|
89
|
+
Aidmock.send(:find_method_on_chain, double, [interface]).should == nil
|
90
|
+
end
|
91
|
+
|
92
|
+
it "use first occurence if more than one on chain can respond to method" do
|
93
|
+
m1 = mock, m2 = mock
|
94
|
+
double = stub(:method => :some)
|
95
|
+
interface = stub
|
96
|
+
interface.stub(:find_method).with(double) { nil }
|
97
|
+
interface2 = stub
|
98
|
+
interface2.stub(:find_method).with(double) { m1 }
|
99
|
+
interface3 = stub
|
100
|
+
interface3.stub(:find_method).with(double) { m2 }
|
101
|
+
|
102
|
+
Aidmock.send(:find_method_on_chain, double, [interface, interface2, interface3]).should == m1
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
context ".class_chain" do
|
107
|
+
it "get chain of defined interfaces on a class" do
|
108
|
+
m1 = mock
|
109
|
+
m2 = mock
|
110
|
+
Aidmock.stub!(:interfaces).and_return({String => m1, Object => m2, Fixnum => true})
|
111
|
+
Aidmock.send(:chain_for, String).should == [m1, m2]
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
context ".extract_class" do
|
116
|
+
it "return the object class if it's an instance" do
|
117
|
+
Aidmock.send(:extract_class, "string").should == String
|
118
|
+
end
|
119
|
+
|
120
|
+
it "return the object if it's an class" do
|
121
|
+
Aidmock.send(:extract_class, String).should == String
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|