2014-04-09 3 views
4

긴 시간 독자하지만 FactoryGirl을 설정했습니다 일 지난 몇은 여기 SO :왜 'FactoryGirl.lint'가 InvalidFactoryError를 제공합니까?

에 처음으로 포스터.

Language.find_or_create_by_code('en') 

으로 :

Language.find_by_code('en') || create(:language) 

첫 번째 옵션 만있는 언어 객체를 생성하기 때문에

어제 나는 대체하여 일부 공장 (주로 내 사용자브랜드 공장) 변경 코드 속성이 채워집니다. 두 번째는 개체를 만들 수있는 언어 팩토리를 사용하는 (따라서 공장에 지정된 모든 속성을 채 웁니다) 이제 나는 즉시 내 사용자 (및이를 admin_user)를 알리는 Factory.lint에 실패 내 테스트를 실행할 때

공장 동안 유효하지 않습니다. 위의 코드를 되 돌리면이 문제가 해결되지 않으며 FactoryGirl.lint에 의해 제공되는 스택 추적은 거의 쓸모가 없습니다.

lint 함수에 주석을 달면 테스트는 실제로 아무런 문제없이 잘 실행됩니다.
수동으로 레일 콘솔에 팩토리를 만들고 .valid?을 사용하면 true를 반환하므로 lint가 내 공장을 유효하지 않은 것으로 간주하는 이유는 무엇입니까? 여기

FactoryGirl.define do 

    factory :user do 
    ignore do 
     lang { Language.find_by_code('en') || create(:language) } 
    end 

    login "test_user" 
    email "[email protected]" 
    name "Jan" 
    password "test1234" 
    password_confirmation "test1234" 
    role    # belongs_to :role 
    brand    # belongs_to :brand 
    person    # belongs_to :person 
    language { lang } # belongs_to :language 

    factory :admin_user do 
     association :role, factory: :admin 
    end 
    end 
end 

역할, 사람 및 공장 (그냥 문자열) 매우 간단하다 언어하지만 브랜드 공장 주와 같은 언어 :

내 사용자 공장은 다음과 같습니다 그래서 FactoryGirl은 내 데이터베이스에 2 개의 'en'언어 항목을 생성하지 않으므로 사용자는 무시 블록에서 코드를 사용합니다.

누구나 내가이 InvalidFactoryError를 얻는 이유를 알 수 있으며이를 디버깅하는 방법에 대한 통찰력을 제공 할 수 있습니까?

:


UPDATE 1

그것은이 문제가
가 나는 공장 VAR 내가 사용자와 특정 위젯을 연결 _widget USER_ 불렀다 .. 다른 공장에 의해 발생합니다 보인다

factory :user_solar_widget, :class => 'UserWidget' do 
    sequence_number 2 
    user { User.find_by_login('test_user') } # || create(:user) } 
    widget { Widget.find_by_type('SolarWidget') || create(:solar_widget) } 
    end 

create (: user) 부분의 주석을 제거하면 사용자 팩토리에 대해 InvalidFactoryError가 발생합니다. User factory에는 user_widgets가 있다는 내용이 없기 때문에 추측 할 수 있습니다. 콜백을 사용하여이 문제를 해결할 수 있는지 실험 해 볼 것입니다.


내 사용자 공장이를 추가하여이 문제를 해결하기 위해 관리했습니다 2

UPDATE : user_widgets은 사용자 모델에 has_many 협회이다

trait :with_widgets do 
    after(:create) do |user| 
    user.user_widgets << create(:user_solar_widget, user: user) 
    end 
end 

. 호출하여

factory :user_solar_widget, :class => 'UserWidget' do 
    sequence_number 2 
    # removed the user line 
    widget { Widget.find_by_type('SolarWidget') || create(:solar_widget) } 
end 

그때 사용자를 만들 :
가 그럼 난 내 user_solar_widget 공장을 변경 린트 기능이 잘못에 대해 조금 더 구체적인 있다면

create :user, :with_widgets 

을 아직도, 그것은 좋았을 것이다 공장 ..

답변

14

FactoryGirl.lint는 존재하지 않는 오류 메시지 때문에 거의 쓸모가 없습니다. 대신 다음 테스트를 포함하는 것이 좋습니다.

# Based on https://github.com/thoughtbot/factory_girl/ 
#   wiki/Testing-all-Factories-(with-RSpec) 
require 'rails_helper' 

RSpec.describe FactoryGirl do 
    described_class.factories.map(&:name).each do |factory_name| 
    describe "#{factory_name} factory" do 
     it 'is valid' do 
     factory = described_class.build(factory_name) 
     expect(factory) 
      .to be_valid, -> { factory.errors.full_messages.join("\n") } 
     end 
    end 
    end 
end