rspec-activemodel-mocks 1.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -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
@@ -0,0 +1,9 @@
1
+ RSpec::Matchers::define :be_included_in_files_in do |path|
2
+ match do |mod|
3
+ stub_metadata(
4
+ :example_group => {:file_path => "#{path}whatever_spec.rb:15"}
5
+ )
6
+ group = RSpec::Core::ExampleGroup.describe
7
+ group.included_modules.include?(mod)
8
+ end
9
+ end