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.
@@ -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