rspec-activemodel-mocks 1.0.0.beta1
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 +7 -0
- data/.yardopts +4 -0
- data/License.txt +23 -0
- data/README.md +70 -0
- data/features/mocks/mock_model.feature +147 -0
- data/features/mocks/stub_model.feature +58 -0
- data/features/step_definitions/additional_cli_steps.rb +4 -0
- data/features/step_definitions/model_steps.rb +3 -0
- data/features/support/env.rb +53 -0
- data/features/support/rubinius.rb +6 -0
- data/lib/rspec/active_model/mocks/mocks.rb +271 -0
- data/lib/rspec/active_model/mocks/version.rb +9 -0
- data/lib/rspec/active_model/mocks.rb +8 -0
- data/lib/rspec-activemodel-mocks.rb +1 -0
- data/spec/rspec/active_model/mocks/mock_model_spec.rb +435 -0
- data/spec/rspec/active_model/mocks/stub_model_spec.rb +154 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/support/ar_classes.rb +42 -0
- data/spec/support/helpers.rb +34 -0
- data/spec/support/matchers.rb +9 -0
- data/spec/support/minitest_support.rb +12 -0
- data/spec/support/null_object.rb +6 -0
- metadata +194 -0
@@ -0,0 +1,435 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "mock_model(RealModel)" do
|
4
|
+
context "given a String" do
|
5
|
+
context "that does not represent an existing constant" do
|
6
|
+
it "class says it's name" do
|
7
|
+
model = mock_model("Foo")
|
8
|
+
expect(model.class.name).to eq("Foo")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
context "that represents an existing constant" do
|
13
|
+
context "that extends ActiveModel::Naming" do
|
14
|
+
it "treats the constant as the class" do
|
15
|
+
model = mock_model("MockableModel")
|
16
|
+
expect(model.class.name).to eq("MockableModel")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context "that does not extend ActiveModel::Naming" do
|
21
|
+
it "raises with a helpful message" do
|
22
|
+
expect do
|
23
|
+
mock_model("String")
|
24
|
+
end.to raise_error(ArgumentError)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context "given a class that does not extend ActiveModel::Naming" do
|
31
|
+
it "raises with a helpful message" do
|
32
|
+
expect do
|
33
|
+
mock_model(String)
|
34
|
+
end.to raise_error(ArgumentError)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "with #id stubbed" do
|
39
|
+
before(:each) do
|
40
|
+
@model = mock_model(MockableModel, :id => 1)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "is named using the stubbed id value" do
|
44
|
+
expect(@model.instance_variable_get(:@name)).to eq("MockableModel_1")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "destroy" do
|
49
|
+
it "sets persisted to false" do
|
50
|
+
model = mock_model(MockableModel)
|
51
|
+
model.destroy
|
52
|
+
expect(model).not_to be_persisted
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "association" do
|
57
|
+
it "constructs a mock association object" do
|
58
|
+
model = mock_model(MockableModel)
|
59
|
+
expect(model.association(:association_name)).to be
|
60
|
+
end
|
61
|
+
|
62
|
+
it "returns a different association object for each association name" do
|
63
|
+
model = mock_model(MockableModel)
|
64
|
+
posts = model.association(:posts)
|
65
|
+
authors = model.association(:authors)
|
66
|
+
|
67
|
+
expect(posts).not_to equal(authors)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "returns the same association model each time for the same association name" do
|
71
|
+
model = mock_model(MockableModel)
|
72
|
+
posts1 = model.association(:posts)
|
73
|
+
posts2 = model.association(:posts)
|
74
|
+
|
75
|
+
expect(posts1).to equal(posts2)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "errors" do
|
80
|
+
context "default" do
|
81
|
+
it "is empty" do
|
82
|
+
model = mock_model(MockableModel)
|
83
|
+
expect(model.errors).to be_empty
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context "with :save => false" do
|
88
|
+
it "is not empty" do
|
89
|
+
model = mock_model(MockableModel, :save => false)
|
90
|
+
expect(model.errors).not_to be_empty
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
context "with :update_attributes => false" do
|
95
|
+
it "is not empty" do
|
96
|
+
model = mock_model(MockableModel, :save => false)
|
97
|
+
expect(model.errors).not_to be_empty
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe "with params" do
|
103
|
+
it "does not mutate its parameters" do
|
104
|
+
params = {:a => 'b'}
|
105
|
+
mock_model(MockableModel, params)
|
106
|
+
expect(params).to eq({:a => 'b'})
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe "as association" do
|
111
|
+
before(:each) do
|
112
|
+
@real = AssociatedModel.create!
|
113
|
+
@mock_model = mock_model(MockableModel)
|
114
|
+
@real.mockable_model = @mock_model
|
115
|
+
end
|
116
|
+
|
117
|
+
it "passes: associated_model == mock" do
|
118
|
+
expect(@mock_model).to eq(@real.mockable_model)
|
119
|
+
end
|
120
|
+
|
121
|
+
it "passes: mock == associated_model" do
|
122
|
+
expect(@real.mockable_model).to eq(@mock_model)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
describe "as association that doesn't exist yet" do
|
127
|
+
before(:each) do
|
128
|
+
@real = AssociatedModel.create!
|
129
|
+
@mock_model = mock_model("Other")
|
130
|
+
@real.nonexistent_model = @mock_model
|
131
|
+
end
|
132
|
+
|
133
|
+
it "passes: associated_model == mock" do
|
134
|
+
expect(@mock_model).to eq(@real.nonexistent_model)
|
135
|
+
end
|
136
|
+
|
137
|
+
it "passes: mock == associated_model" do
|
138
|
+
expect(@real.nonexistent_model).to eq(@mock_model)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
describe "#is_a?" do
|
143
|
+
before(:each) do
|
144
|
+
@model = mock_model(SubMockableModel)
|
145
|
+
end
|
146
|
+
|
147
|
+
it "says it is_a?(RealModel)" do
|
148
|
+
expect(@model.is_a?(SubMockableModel)).to be(true)
|
149
|
+
end
|
150
|
+
|
151
|
+
it "says it is_a?(OtherModel) if RealModel is an ancestors" do
|
152
|
+
expect(@model.is_a?(MockableModel)).to be(true)
|
153
|
+
end
|
154
|
+
|
155
|
+
it "can be stubbed" do
|
156
|
+
expect(mock_model(MockableModel, :is_a? => true).is_a?(:Foo)).to be_truthy
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
describe "#kind_of?" do
|
161
|
+
before(:each) do
|
162
|
+
@model = mock_model(SubMockableModel)
|
163
|
+
end
|
164
|
+
|
165
|
+
it "says it is kind_of? if RealModel is" do
|
166
|
+
expect(@model.kind_of?(SubMockableModel)).to be(true)
|
167
|
+
end
|
168
|
+
|
169
|
+
it "says it is kind_of? if RealModel's ancestor is" do
|
170
|
+
expect(@model.kind_of?(MockableModel)).to be(true)
|
171
|
+
end
|
172
|
+
|
173
|
+
it "can be stubbed" do
|
174
|
+
expect(mock_model(MockableModel, :kind_of? => true).kind_of?(:Foo)).to be_truthy
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
describe "#instance_of?" do
|
179
|
+
before(:each) do
|
180
|
+
@model = mock_model(SubMockableModel)
|
181
|
+
end
|
182
|
+
|
183
|
+
it "says it is instance_of? if RealModel is" do
|
184
|
+
expect(@model.instance_of?(SubMockableModel)).to be(true)
|
185
|
+
end
|
186
|
+
|
187
|
+
it "does not say it instance_of? if RealModel isn't, even if it's ancestor is" do
|
188
|
+
expect(@model.instance_of?(MockableModel)).to be(false)
|
189
|
+
end
|
190
|
+
|
191
|
+
it "can be stubbed" do
|
192
|
+
expect(mock_model(MockableModel, :instance_of? => true).instance_of?(:Foo)).to be_truthy
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
describe "#has_attribute?" do
|
197
|
+
context "with an ActiveRecord model" do
|
198
|
+
before(:each) do
|
199
|
+
MockableModel.stub(:column_names).and_return(["column_a", "column_b"])
|
200
|
+
@model = mock_model(MockableModel)
|
201
|
+
end
|
202
|
+
|
203
|
+
it "has a given attribute if the underlying model has column of the same name" do
|
204
|
+
expect(@model.has_attribute?("column_a")).to be_truthy
|
205
|
+
expect(@model.has_attribute?("column_b")).to be_truthy
|
206
|
+
expect(@model.has_attribute?("column_c")).to be_falsey
|
207
|
+
end
|
208
|
+
|
209
|
+
it "accepts symbols" do
|
210
|
+
expect(@model.has_attribute?(:column_a)).to be_truthy
|
211
|
+
expect(@model.has_attribute?(:column_b)).to be_truthy
|
212
|
+
expect(@model.has_attribute?(:column_c)).to be_falsey
|
213
|
+
end
|
214
|
+
|
215
|
+
it "allows has_attribute? to be explicitly stubbed" do
|
216
|
+
@model = mock_model(MockableModel, :has_attribute? => false)
|
217
|
+
expect(@model.has_attribute?(:column_a)).to be_falsey
|
218
|
+
expect(@model.has_attribute?(:column_b)).to be_falsey
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
describe "#respond_to?" do
|
224
|
+
context "with an ActiveRecord model" do
|
225
|
+
before(:each) do
|
226
|
+
allow(MockableModel).to receive(:column_names).and_return(["column_a", "column_b"])
|
227
|
+
@model = mock_model(MockableModel)
|
228
|
+
end
|
229
|
+
|
230
|
+
it "accepts two arguments" do
|
231
|
+
expect do
|
232
|
+
@model.respond_to?("title_before_type_cast", false)
|
233
|
+
end.to_not raise_exception
|
234
|
+
end
|
235
|
+
|
236
|
+
context "without as_null_object" do
|
237
|
+
it "says it will respond_to?(key) if RealModel has the attribute 'key'" do
|
238
|
+
expect(@model.respond_to?("column_a")).to be(true)
|
239
|
+
end
|
240
|
+
it "stubs column accessor (with string)" do
|
241
|
+
@model.respond_to?("column_a")
|
242
|
+
expect(@model.column_a).to be_nil
|
243
|
+
end
|
244
|
+
it "stubs column accessor (with symbol)" do
|
245
|
+
@model.respond_to?(:column_a)
|
246
|
+
expect(@model.column_a).to be_nil
|
247
|
+
end
|
248
|
+
it "does not stub column accessor if already stubbed in declaration (with string)" do
|
249
|
+
model = mock_model(MockableModel, "column_a" => "a")
|
250
|
+
model.respond_to?("column_a")
|
251
|
+
expect(model.column_a).to eq("a")
|
252
|
+
end
|
253
|
+
it "does not stub column accessor if already stubbed in declaration (with symbol)" do
|
254
|
+
model = mock_model(MockableModel, :column_a => "a")
|
255
|
+
model.respond_to?("column_a")
|
256
|
+
expect(model.column_a).to eq("a")
|
257
|
+
end
|
258
|
+
it "does not stub column accessor if already stubbed after declaration (with string)" do
|
259
|
+
allow(@model).to receive(:column_a) { "a" }
|
260
|
+
@model.respond_to?("column_a")
|
261
|
+
expect(@model.column_a).to eq("a")
|
262
|
+
end
|
263
|
+
it "does not stub column accessor if already stubbed after declaration (with symbol)" do
|
264
|
+
allow(@model).to receive(:column_a) { "a" }
|
265
|
+
@model.respond_to?("column_a")
|
266
|
+
expect(@model.column_a).to eq("a")
|
267
|
+
end
|
268
|
+
it "says it will not respond_to?(key) if RealModel does not have the attribute 'key'" do
|
269
|
+
expect(@model.respond_to?("column_c")).to be(false)
|
270
|
+
end
|
271
|
+
it "says it will not respond_to?(xxx_before_type_cast)" do
|
272
|
+
expect(@model.respond_to?("title_before_type_cast")).to be(false)
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
context "with as_null_object" do
|
277
|
+
it "says it will respond_to?(key) if RealModel has the attribute 'key'" do
|
278
|
+
expect(@model.as_null_object.respond_to?("column_a")).to be(true)
|
279
|
+
end
|
280
|
+
it "says it will respond_to?(key) even if RealModel does not have the attribute 'key'" do
|
281
|
+
expect(@model.as_null_object.respond_to?("column_c")).to be(true)
|
282
|
+
end
|
283
|
+
it "says it will not respond_to?(xxx_before_type_cast)" do
|
284
|
+
expect(@model.as_null_object.respond_to?("title_before_type_cast")).to be(false)
|
285
|
+
end
|
286
|
+
it "returns self for any unprepared message" do
|
287
|
+
@model.as_null_object.tap do |x|
|
288
|
+
expect(x.non_existant_message).to be(@model)
|
289
|
+
end
|
290
|
+
end
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
context "with a non-ActiveRecord model" do
|
295
|
+
it "responds as normal" do
|
296
|
+
model = NonActiveRecordModel.new
|
297
|
+
expect(model).to respond_to(:to_param)
|
298
|
+
end
|
299
|
+
|
300
|
+
context "with as_null_object" do
|
301
|
+
it "says it will not respond_to?(xxx_before_type_cast)" do
|
302
|
+
model = NonActiveRecordModel.new.as_null_object
|
303
|
+
expect(model.respond_to?("title_before_type_cast")).to be(false)
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
it "can be stubbed" do
|
309
|
+
expect(mock_model(MockableModel, :respond_to? => true).respond_to?(:foo)).to be_truthy
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
describe "#class" do
|
314
|
+
it "returns the mocked model" do
|
315
|
+
expect(mock_model(MockableModel).class).to eq(MockableModel)
|
316
|
+
end
|
317
|
+
|
318
|
+
it "can be stubbed" do
|
319
|
+
expect(mock_model(MockableModel, :class => String).class).to be(String)
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
describe "#to_s" do
|
324
|
+
it "returns (model.name)_(model#to_param)" do
|
325
|
+
expect(mock_model(MockableModel).to_s).to eq("MockableModel_#{to_param}")
|
326
|
+
end
|
327
|
+
|
328
|
+
it "can be stubbed" do
|
329
|
+
expect(mock_model(MockableModel, :to_s => "this string").to_s).to eq("this string")
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
333
|
+
describe "#destroyed?" do
|
334
|
+
context "default" do
|
335
|
+
it "returns false" do
|
336
|
+
@model = mock_model(SubMockableModel)
|
337
|
+
expect(@model.destroyed?).to be(false)
|
338
|
+
end
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
describe "#marked_for_destruction?" do
|
343
|
+
context "default" do
|
344
|
+
it "returns false" do
|
345
|
+
@model = mock_model(SubMockableModel)
|
346
|
+
expect(@model.marked_for_destruction?).to be(false)
|
347
|
+
end
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
describe "#persisted?" do
|
352
|
+
context "with default identifier" do
|
353
|
+
it "returns true" do
|
354
|
+
expect(mock_model(MockableModel)).to be_persisted
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
context "with explicit identifier via :id" do
|
359
|
+
it "returns true" do
|
360
|
+
expect(mock_model(MockableModel, :id => 37)).to be_persisted
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
context "with id => nil" do
|
365
|
+
it "returns false" do
|
366
|
+
expect(mock_model(MockableModel, :id => nil)).not_to be_persisted
|
367
|
+
end
|
368
|
+
end
|
369
|
+
end
|
370
|
+
|
371
|
+
describe "#valid?" do
|
372
|
+
context "default" do
|
373
|
+
it "returns true" do
|
374
|
+
expect(mock_model(MockableModel)).to be_valid
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
378
|
+
context "stubbed with false" do
|
379
|
+
it "returns false" do
|
380
|
+
expect(mock_model(MockableModel, :valid? => false)).not_to be_valid
|
381
|
+
end
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
385
|
+
describe "#as_new_record" do
|
386
|
+
it "says it is a new record" do
|
387
|
+
m = mock_model(MockableModel)
|
388
|
+
expect(m.as_new_record).to be_new_record
|
389
|
+
end
|
390
|
+
|
391
|
+
it "says it is not persisted" do
|
392
|
+
m = mock_model(MockableModel)
|
393
|
+
expect(m.as_new_record).not_to be_persisted
|
394
|
+
end
|
395
|
+
|
396
|
+
it "has a nil id" do
|
397
|
+
expect(mock_model(MockableModel).as_new_record.id).to be(nil)
|
398
|
+
end
|
399
|
+
|
400
|
+
it "returns nil for #to_param" do
|
401
|
+
expect(mock_model(MockableModel).as_new_record.to_param).to be(nil)
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
405
|
+
describe "#blank?" do
|
406
|
+
it "is false" do
|
407
|
+
expect(mock_model(MockableModel)).not_to be_blank
|
408
|
+
end
|
409
|
+
end
|
410
|
+
|
411
|
+
describe "ActiveModel Lint tests" do
|
412
|
+
begin
|
413
|
+
require 'minitest/assertions'
|
414
|
+
include Minitest::Assertions
|
415
|
+
include MinitestAssertion
|
416
|
+
rescue LoadError
|
417
|
+
require 'test/unit/assertions'
|
418
|
+
include Test::Unit::Assertions
|
419
|
+
end
|
420
|
+
|
421
|
+
require 'active_model/lint'
|
422
|
+
include ActiveModel::Lint::Tests
|
423
|
+
|
424
|
+
# to_s is to support ruby-1.9
|
425
|
+
ActiveModel::Lint::Tests.public_instance_methods.map{|m| m.to_s}.grep(/^test/).each do |m|
|
426
|
+
example m.gsub('_',' ') do
|
427
|
+
send m
|
428
|
+
end
|
429
|
+
end
|
430
|
+
|
431
|
+
def model
|
432
|
+
mock_model(MockableModel, :id => nil)
|
433
|
+
end
|
434
|
+
end
|
435
|
+
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "stub_model" do
|
4
|
+
|
5
|
+
shared_examples_for "stub model" do
|
6
|
+
describe "with a block" do
|
7
|
+
it "yields the model" do
|
8
|
+
model = stub_model(model_class) do |block_arg|
|
9
|
+
@block_arg = block_arg
|
10
|
+
end
|
11
|
+
expect(model).to be(@block_arg)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#persisted?" do
|
16
|
+
context "default" do
|
17
|
+
it "returns true" do
|
18
|
+
model = stub_model(model_class)
|
19
|
+
expect(model).to be_persisted
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context "with as_new_record" do
|
24
|
+
it "returns false" do
|
25
|
+
model = stub_model(model_class).as_new_record
|
26
|
+
expect(model).not_to be_persisted
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
it "increments the value returned by to_param" do
|
32
|
+
first = stub_model(model_class)
|
33
|
+
second = stub_model(model_class)
|
34
|
+
expect(second.to_param.to_i).to eq(first.to_param.to_i + 1)
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "#blank?" do
|
38
|
+
it "is false" do
|
39
|
+
expect(stub_model(model_class)).not_to be_blank
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context "with ActiveModel (not ActiveRecord)" do
|
45
|
+
it_behaves_like "stub model" do
|
46
|
+
def model_class
|
47
|
+
NonActiveRecordModel
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context "with an ActiveRecord model" do
|
53
|
+
let(:model_class) { MockableModel }
|
54
|
+
|
55
|
+
it_behaves_like "stub model"
|
56
|
+
|
57
|
+
describe "#new_record?" do
|
58
|
+
context "default" do
|
59
|
+
it "returns false" do
|
60
|
+
model = stub_model(model_class)
|
61
|
+
expect(model.new_record?).to be_falsey
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "with as_new_record" do
|
66
|
+
it "returns true" do
|
67
|
+
model = stub_model(model_class).as_new_record
|
68
|
+
expect(model.new_record?).to be_truthy
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "defaults" do
|
74
|
+
it "has an id" do
|
75
|
+
expect(stub_model(MockableModel).id).to be > 0
|
76
|
+
end
|
77
|
+
|
78
|
+
it "says it is not a new record" do
|
79
|
+
expect(stub_model(MockableModel)).not_to be_new_record
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe "#as_new_record" do
|
84
|
+
it "has a nil id" do
|
85
|
+
expect(stub_model(MockableModel).as_new_record.id).to be(nil)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
it "raises when hitting the db" do
|
90
|
+
expect do
|
91
|
+
stub_model(MockableModel).connection
|
92
|
+
end.to raise_error(RSpec::ActiveModel::Mocks::IllegalDataAccessException, /stubbed models are not allowed to access the database/)
|
93
|
+
end
|
94
|
+
|
95
|
+
it "increments the id" do
|
96
|
+
first = stub_model(model_class)
|
97
|
+
second = stub_model(model_class)
|
98
|
+
expect(second.id).to eq(first.id + 1)
|
99
|
+
end
|
100
|
+
|
101
|
+
it "accepts a stub id" do
|
102
|
+
expect(stub_model(MockableModel, :id => 37).id).to eq(37)
|
103
|
+
end
|
104
|
+
|
105
|
+
it "says it is a new record when id is set to nil" do
|
106
|
+
expect(stub_model(MockableModel, :id => nil)).to be_new_record
|
107
|
+
end
|
108
|
+
|
109
|
+
it "accepts a stub for save" do
|
110
|
+
expect(stub_model(MockableModel, :save => false).save).to be(false)
|
111
|
+
end
|
112
|
+
|
113
|
+
describe "alternate primary key" do
|
114
|
+
it "has the correct primary_key name" do
|
115
|
+
expect(stub_model(AlternatePrimaryKeyModel).class.primary_key.to_s).to eq('my_id')
|
116
|
+
end
|
117
|
+
|
118
|
+
it "has a primary_key" do
|
119
|
+
expect(stub_model(AlternatePrimaryKeyModel).my_id).to be > 0
|
120
|
+
end
|
121
|
+
|
122
|
+
it "says it is not a new record" do
|
123
|
+
stub_model(AlternatePrimaryKeyModel) do |m|
|
124
|
+
expect(m).not_to be_new_record
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
it "says it is a new record if primary_key is nil" do
|
129
|
+
expect(stub_model(AlternatePrimaryKeyModel, :my_id => nil)).to be_new_record
|
130
|
+
end
|
131
|
+
|
132
|
+
it "accepts a stub for the primary_key" do
|
133
|
+
expect(stub_model(AlternatePrimaryKeyModel, :my_id => 5).my_id).to eq(5)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe "as association" do
|
138
|
+
before(:each) do
|
139
|
+
@real = AssociatedModel.create!
|
140
|
+
@stub_model = stub_model(MockableModel)
|
141
|
+
@real.mockable_model = @stub_model
|
142
|
+
end
|
143
|
+
|
144
|
+
it "passes associated_model == mock" do
|
145
|
+
expect(@stub_model).to eq(@real.mockable_model)
|
146
|
+
end
|
147
|
+
|
148
|
+
it "passes mock == associated_model" do
|
149
|
+
expect(@real.mockable_model).to eq(@stub_model)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rspec/active_model/mocks'
|
2
|
+
require 'active_record'
|
3
|
+
|
4
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
5
|
+
|
6
|
+
class RSpec::Core::ExampleGroup
|
7
|
+
def self.run_all(reporter=nil)
|
8
|
+
run(reporter || RSpec::Mocks::Mock.new('reporter').as_null_object)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
RSpec.configure do |config|
|
13
|
+
real_world = nil
|
14
|
+
|
15
|
+
config.filter_run :focus
|
16
|
+
config.run_all_when_everything_filtered = true
|
17
|
+
config.before(:each) do
|
18
|
+
real_world = RSpec.world
|
19
|
+
RSpec.instance_variable_set(:@world, RSpec::Core::World.new)
|
20
|
+
end
|
21
|
+
config.after(:each) do
|
22
|
+
RSpec.instance_variable_set(:@world, real_world)
|
23
|
+
end
|
24
|
+
|
25
|
+
config.order = :random
|
26
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
ActiveRecord::Base.establish_connection(
|
2
|
+
:adapter => 'sqlite3',
|
3
|
+
:database => ':memory:'
|
4
|
+
)
|
5
|
+
|
6
|
+
module Connections
|
7
|
+
def self.extended(host)
|
8
|
+
host.connection.execute <<-eosql
|
9
|
+
CREATE TABLE #{host.table_name} (
|
10
|
+
#{host.primary_key} integer PRIMARY KEY AUTOINCREMENT,
|
11
|
+
associated_model_id integer,
|
12
|
+
mockable_model_id integer,
|
13
|
+
nonexistent_model_id integer
|
14
|
+
)
|
15
|
+
eosql
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class NonActiveRecordModel
|
20
|
+
extend ActiveModel::Naming
|
21
|
+
include ActiveModel::Conversion
|
22
|
+
end
|
23
|
+
|
24
|
+
class MockableModel < ActiveRecord::Base
|
25
|
+
extend Connections
|
26
|
+
has_one :associated_model
|
27
|
+
end
|
28
|
+
|
29
|
+
class SubMockableModel < MockableModel
|
30
|
+
end
|
31
|
+
|
32
|
+
class AssociatedModel < ActiveRecord::Base
|
33
|
+
extend Connections
|
34
|
+
belongs_to :mockable_model
|
35
|
+
belongs_to :nonexistent_model, :class_name => "Other"
|
36
|
+
end
|
37
|
+
|
38
|
+
class AlternatePrimaryKeyModel < ActiveRecord::Base
|
39
|
+
self.primary_key = :my_id
|
40
|
+
extend Connections
|
41
|
+
attr_accessor :my_id
|
42
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Helpers
|
2
|
+
def stub_metadata(additional_metadata)
|
3
|
+
stub_metadata = metadata_with(additional_metadata)
|
4
|
+
allow(RSpec::Core::ExampleGroup).to receive(:metadata) { stub_metadata }
|
5
|
+
end
|
6
|
+
|
7
|
+
def metadata_with(additional_metadata)
|
8
|
+
m = RSpec::Core::Metadata.new
|
9
|
+
m.process("example group")
|
10
|
+
|
11
|
+
group_metadata = additional_metadata.delete(:example_group)
|
12
|
+
if group_metadata
|
13
|
+
m[:example_group].merge!(group_metadata)
|
14
|
+
end
|
15
|
+
m.merge!(additional_metadata)
|
16
|
+
m
|
17
|
+
end
|
18
|
+
|
19
|
+
def with_isolated_config
|
20
|
+
original_config = RSpec.configuration
|
21
|
+
RSpec.configuration = RSpec::Core::Configuration.new
|
22
|
+
RSpec.configure do |c|
|
23
|
+
c.include RSpec::Rails::FixtureSupport
|
24
|
+
c.add_setting :use_transactional_fixtures, :alias_with => :use_transactional_examples
|
25
|
+
c.add_setting :use_instantiated_fixtures
|
26
|
+
c.add_setting :global_fixtures
|
27
|
+
c.add_setting :fixture_path
|
28
|
+
end
|
29
|
+
yield
|
30
|
+
RSpec.configuration = original_config
|
31
|
+
end
|
32
|
+
|
33
|
+
RSpec.configure {|c| c.include self}
|
34
|
+
end
|