It is difficult to create a unit test on rspec using factory_gir in the polymorphic association.
I used a very basic example for the experiment
Even in the basic example, there is an error that I can't understand why, so I'm asking for your help...
# db/schema.rb
ActiveRecord::Schema.define(version: 20160412134106) do
create_table "cars", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "pictures", force: :cascade do |t|
t.integer "imageable_id"
t.string "imageable_type"
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
The schema is as above
I did a very basic polymorphic association.
# app/models/picture.rb
class Picture < ActiveRecord::Base
belongs_to :imageable, polymorphic: true
end
# app/models/car.rb
class Car < ActiveRecord::Base
has_many :pictures, as: :imageable
end
As shown above, we configured the same as rails polymorphic example.
And I wrote the test using factory girl and rspec as below...
# spec/factories/pictures.rb
FactoryGirl.define do
factory :car_picture do
association :imageable, factory: :car
end
end
# spec/factories/cars.rb
FactoryGirl.define do
factory :car do
name "MyString"
end
end
# spec/models/car_spec.rb
require 'rails_helper'
RSpec.describe Car, type: :model do
let(:car_picture) { build(:car_pictur) }
it { expect(car_picture).to validate_uniqueness_of(:imageable_type).scoped_to(:imageable_id) }
end
When you run the rspec command,
$ bundle exec rspec -b
F
Failures:
1) 1) Car
Failure/Error: let(:car_picture) { build(:car_picture) }
NameError:
uninitialized constant CarPicture
...
Finished in 0.00241 seconds (files took 1.4 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/models/car_spec.rb:5 # Car
$
As above, the error initialized constant Car Picture
appears, but I don't know why...
The error mentioned in the comment was reproduced in the questioning project.
# app/models/picture.rb
class Picture < ActiveRecord::Base
belongs_to :imageable, polymorphic: true
validates :imageable_type, uniquence: { scope: :imageable_id} # Added row!!!!!
validates :imageable, presence: true # Added row!!!!!!!
end
Other codes added class: Picture
that is used when the factory name and the class name are different, and the rest are all the same, and at the end of the picture.rb above, validates:imageable, presence: true #added row!!!!!
The following error occurs. (The comment also mentioned...))
$ bundle exec rspec
F
Failures:
1) 1) Car should validate that :imageable_type is case-sensitively unique within the scope of :imageable_id
Failure/Error: it { expect(car_picture).to validate_uniqueness_of(:imageable_type).scoped_to(:imageable_id) }
NameError:
wrong constant name cAR
# # ./spec/models/car_spec.rb:5:in `block (2 levels) in <top (required)>'
Finished in 0.03813 seconds (files took 1.39 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/models/car_spec.rb:5 # Car should validate that :imageable_type is case-sensitively unique within the scope of :imageable_id
$
In spec/factories/pictures.rb
FactoryGirl.define do
factory :car_picture, class: Picture do
association :imageable, factory: :user
end
end
Changing to user instead of car
$ bundle exec rspec
F
Failures:
1) 1) Car should validate that :imageable_type is case-sensitively unique within the scope of :imageable_id
Failure/Error: it { expect(car_picture).to validate_uniqueness_of(:imageable_type).scoped_to(:imageable_id) }
NameError:
wrong constant name uSER
# # ./spec/models/car_spec.rb:5:in `block (2 levels) in <top (required)>'
Finished in 0.04852 seconds (files took 2.14 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/models/car_spec.rb:5 # Car should validate that :imageable_type is case-sensitively unique within the scope of :imageable_id
$
Like wrong constant name uSER
above, only the first letter of the model name was lowercase and all the rest were capitalized, and if the model name was UserFriend, there was an error with uSERfRIEND
...
What's the problem?
rspec factory_girl ruby-on-rails
Problem:
# spec/factories/pictures.rb
FactoryGirl.define do
factory :car_picture do
association :imageable, factory: :car
end
end
factory:car_picture
defined in specs/factories/pictures.rb
is the problematic part.
Solution:
If the Factory name is different from the class name,
FactoryGirl.define do
factory :car_picture, class: Picture
...
end
end
You have to define it like this.
If you use the concept of inheritance
FactoryGirl.define do
factory :picture do
... # Common attributes are here
end
factory :car_picture, parent: :picture do
association :imageable, factory: :car
end
end
You can use it like this.
Problem:
NameError:
wrong constant name cAR
The validate_unique_of
method in shoulda-matchers
creates two objects internally to test uniquence. One creates two objects with values that are different from the attribute defined as uniquence, and the other with values that are different from the attribute defined as uniquence.
The attribute you are about to test uniquence is :imageable_type
of the polymorphic association.
In the process of creating two objects to test uniquence,
You want to create an object with the "Car"
class name and create an object with the "cAR"
class name, but an error occurs because the class cAR
does not exist.
Solution:
Workaround is,
class Picture < Active Record::Base
...
validates :imageable_id, uniqueness: { scope: :imageable_type }
end
RSspec.describe Car, type::model do
...
it { expect(car_picture).to validate_uniqueness_of(:imageable_id).scoped_to(:imageable_type) }
end
If you set the attribute of the unity you want to test as imageable_id
and define imageable_type
as scope, you can do the test you want.
© 2024 OneMinuteCode. All rights reserved.