rspec에서 NameError: wrong constant name 오류 해결
조회수 1451회
polymorphic association에서 factory_gir을 사용하여 rspec 상에서 unit test를 작성하는데 어려움이 있습니다.
실험을 위해서 아주 기본 예제로 하였는데
기본예제에서도 왜인지 파악되지 않는 오류가 있어서 이렇게 도움을 청합니다...
# 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
schema가 위와 같이 되어있고,
아주 기본적인 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
위와 같이 rails polymorphic 예제와 동일하게 구성해보았습니다.
그리고 factory girl과 rspec를 이용해서 test를 아래와 같이 작성하였는데요...
# 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
rspec 명령을 수행하면
$ bundle exec rspec -b
F
Failures:
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
$
위와 같이 uninitialized constant CarPicture
라는 오류가 나는데 왜 나는지 모르겠네요...
추가 질문
댓글에서 언급한 오류를 질문용 프로젝트에도 재현하였습니다.
# app/models/picture.rb
class Picture < ActiveRecord::Base
belongs_to :imageable, polymorphic: true
validates :imageable_type, uniqueness: { scope: :imageable_id } # 추가된 행!!!!!!!
validates :imageable, presence: true # 추가된 행!!!!!!!
end
다른 코드들은 답변으로 제시해주신 factory명과 해당 클래스명이 다를때 사용하는 class: Picture
를 추가하였고, 나머지는 전부 같고 위 picture.rb에서 마지막쯤에 validates :imageable, presence: true # 추가된 행!!!!!!!
을 추가하고 test를 돌리니
아래와 같은 오류가 발생합니다.(댓글에서도 언급한..)
$ bundle exec rspec
F
Failures:
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
$
spec/factories/pictures.rb
에서
FactoryGirl.define do
factory :car_picture, class: Picture do
association :imageable, factory: :user
end
end
car대신 user로 바꾸니
$ bundle exec rspec
F
Failures:
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
$
위와 같이 wrong constant name uSER
과 같이 모델이름에서 첫문자만 소문자이고 나머지는 전부 대문자로 되는현상이 보였고, 모델이름이 UserFriend라면 uSERfRIEND
로 오류가 나느 현상이 보여졌습니다...
뭐가 문제일까요?
-
(•́ ✖ •̀)
알 수 없는 사용자
2 답변
-
Problem:
# spec/factories/pictures.rb FactoryGirl.define do factory :car_picture do association :imageable, factory: :car end end
spec/factories/pictures.rb
에 정의하신factory :car_picture
이 부분이 문제가 되는 부분인데요.Solution:
Factory명이 해당 클래스명과 다를시엔,
FactoryGirl.define do factory :car_picture, class: Picture ... end end
이렇게 정의 해주셔야합니다.
만약, 상속 개념을 사용하신다면
FactoryGirl.define do factory :picture do ... # 공통적으로 사용할 attributes은 여기로 end factory :car_picture, parent: :picture do association :imageable, factory: :car end end
이런식으로 사용하시면 됩니다.
-
(•́ ✖ •̀)
알 수 없는 사용자 -
(•́ ✖ •̀)
알 수 없는 사용자 - 〉
- 답변감사합니다. 예제코드에서는 말씀해주신대로 하니까 잘 됐는데... 실제 프로젝트 코드에서는 또 요상하게 오류가 나네요... `wrong constant name uSER` 이런식...? 알 수 없는 사용자 2016.4.13 02:02
- 저 user이 `association :imageable, factory: :car` 이부분에서 car대신 :user을 넣었더니 저렇게 되고 저 자리에 또 다른 (실제 있는) factory를 넣으니까 같은 형태로 첫문자만 소문자 뒷 문자는 전부 대문자로 오류가 나네요... car을 넣으면 cAR, card를 넣으면 cARD... 이건 뭘까요...? 알 수 없는 사용자 2016.4.13 02:05
- stacktrace는 거의 비슷하네요...? 똑같나... 아무튼 얼핏 보기에 똑같습니다... 알 수 없는 사용자 2016.4.13 02:06
- 새로 발생하는 문제에 대해선 질문을 새로 작성해서 작성하신 코드와 함께 올려주세요. 코드 없이 설명만으론 문제점을 찾기가 힘드네요. 알 수 없는 사용자 2016.4.13 02:52
- @김현일님 계속적인 답변 감사드립니다. 윗 댓글에서 언급한 새로 발생한 문제에 대해서 본문에 추가하였습니다. 한번서 살펴봐 주셔요... 감사합니다! 알 수 없는 사용자 2016.4.13 13:49
-
-
추가 질문에 대한 답변
Problem:
NameError: wrong constant name cAR
shoulda-matchers
의validate_uniqueness_of
메소드는 uniqueness를 테스트하기 위해서 내부적으로 두개의 객체를 생성합니다. 한개는 uniqueness로 정의된 attribute과 같은 값, 또 하나는 uniqueness로 정의된 attribute과 다른 값을 가진 객체 두개를 생성합니다.지금 uniqueness를 테스트하려는 attribute이, polymorphic association의
:imageable_type
인데,uniqueness를 테스트하기 위해 두개의 객체를 생성하는 과정에서
"Car"
클래스명을 가진 객체를 하나 생성하고,"cAR"
클래스명을 가진 객체를 하나 생성하려고 하는데,cAR
라는 클래스가 존재하지 않기 때문에 에러가 발생하는 것입니다.- 여기서
"cAR"
클래스명이 어떻게 나왔냐면,shoulda-matchers
내부적으로 다른 값을 생성할 때,value.swapcase
와,value.next
이 두가지 메소드를 사용하여 다른 값을 생성합니다. 여기서"Car".swapcase
의 결과 값이"cAR"
이 됩니다. (참고:"User".swapcase
의 결과 값은"uSER"
).
Solution:
해결 방법은,
class Picture < ActiveRecord::Base ... validates :imageable_id, uniqueness: { scope: :imageable_type } end
RSpec.describe Car, type: :model do ... it { expect(car_picture).to validate_uniqueness_of(:imageable_id).scoped_to(:imageable_type) } end
테스트하려는 uniqueness의 attribute를
imageable_id
으로 하고,imageable_type
을 scope으로 정의하면 원하시는 테스트를 하실 수 있을거같습니다.-
(•́ ✖ •̀)
알 수 없는 사용자 -
(•́ ✖ •̀)
알 수 없는 사용자 - 〉
- 여기서
댓글 입력