NameError: wrong constant name error resolution in rspec

Asked 2 years ago, Updated 2 years ago, 67 views

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

2022-09-21 14:52

2 Answers

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.


2022-09-21 14:52

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.


2022-09-21 14:52

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.