RSpec与FactoryGirl / Bot - 未定义的方法'用户'在通过has_many属于用户的模型上:通过

时间:2017-11-25 04:53:05

标签: ruby rspec factory-bot rspec-rails

尝试进行正确的测试,并使用FactoryBot找出基本RSpec的细节。

注意:验证测试全部先前已通过,并且它们位于模型文件中。我为了减少混乱而删除了它们。

我的模特:

models/user.rb

has_many :fulfillments
has_many :milestones, through: :fulfillments


models/fulfillment.rb

has_many :milestones
belongs_to :user


models/milestone.rb

belongs_to :fulfillments

我的工厂:

规格/工厂/ users.rb的

require 'faker'

FactoryBot.define do
  factory :user do
    first_name  Faker::Name.first_name
    last_name  Faker::Name.last_name
    preferred_name  Faker::Name.first_name
    username  Faker::Internet.user_name
    email  Faker::Internet.email
    password  'password123'
    password_confirmation  'password123'

    factory :user_with_fulfillments do
      transient do
        fulfillments_count 3
       end

      after(:create) do |user, e|
        create_list(:fulfillment_with_milestones, e.fulfillments_count, user: user)
      end
    end
  end
end

规格/工厂/ fulfillments.rb

require 'faker'

FactoryBot.define do
  factory :fulfillment do
    title Faker::Lorem.words.join(' ')
    description Faker::Lorem.sentences.join(' ')
    promise Faker::Lorem.sentence
    reason Faker::Lorem.sentence
    association :user, factory: :user_with_fulfillments

    trait :userless do
      user nil
    end

    factory :fulfillment_with_milestones do
      transient do
        milestones_count 2
      end

      after(:create) do |fulfillment, e|
        create_list(:milestone, e.milestones_count, fulfillment: fulfillment)
      end
    end
  end
end

规格/工厂/ milestones.rb

require 'faker'

FactoryBot.define do
  factory :milestone do
    title Faker::Lorem.words.join(' ')
    criteria Faker::Lorem.sentences.join("\n")
    reason Faker::Lorem.sentence    
    deadline Faker::Date.forward(30)

    association :fulfillment, factory: :fulfillment_with_milestones
  end
end

一次给我带来麻烦的测试(spec / models / milestone.rb)

require 'rails_helper'

RSpec.describe Milestone, type: :model do

  it 'has a valid factory' do
    expect(create(:milestone)).to be_valid
  end

  it 'validates attributes correctly' do
    should validate_presence_of :fulfillment
    should validate_presence_of :title
    should validate_presence_of :criteria
  end

end

错误我参与任何涉及里程碑工厂的测试

故障:

  1) Fulfillment has a valid factory
 Failure/Error: create_list(:milestone, e.milestones_count, fulfillment: fulfillment)

 NoMethodError:
   undefined method `user' for #<Milestone:0x00007f844d54f1b8>
 # ./spec/factories/fulfillments.rb:22:in `block (4 levels) in <top (required)>'
 # ./spec/factories/users.rb:19:in `block (4 levels) in <top (required)>'
 # ./spec/models/fulfillment_spec.rb:6:in `block (2 levels) in <top (required)>'

  2) Milestone has a valid factory
 Failure/Error: expect(create(:milestone)).to be_valid

 NoMethodError:
   undefined method `user' for #<Milestone:0x00007f844d8d0b98>
 # ./spec/models/milestone_spec.rb:6:in `block (2 levels) in <top (required)>'

  3) Milestone validates attributes correctly
 Failure/Error: should validate_presence_of :fulfillment

 NoMethodError:
   undefined method `user' for #<Milestone:0x00007f8450829700>
 # ./spec/models/milestone_spec.rb:10:in `block (2 levels) in <top (required)>'

  4) User can have fulfillments and milestones
 Failure/Error: create_list(:milestone, e.milestones_count, fulfillment: fulfillment)

 NoMethodError:
   undefined method `user' for #<Milestone:0x00007f8450b7b9d0>
 # ./spec/factories/fulfillments.rb:22:in `block (4 levels) in <top (required)>'
 # ./spec/factories/users.rb:19:in `block (4 levels) in <top (required)>'
 # ./spec/models/user_spec.rb:29:in `block (2 levels) in <top (required)>'

Finished in 0.26253 seconds (files took 5.19 seconds to load)

9个例子,4个失败,1个未决

Failed examples:

rspec ./spec/models/fulfillment_spec.rb:5 # Fulfillment has a valid factory
rspec ./spec/models/milestone_spec.rb:5 # Milestone has a valid factory
rspec ./spec/models/milestone_spec.rb:9 # Milestone validates attributes correctly
rspec ./spec/models/user_spec.rb:28 # User can have fulfillments and milestones

大部分时间都很困惑,因为我不知道它试图在里程碑实例上调用#user的地点或原因。工厂为用户创建了Fulfillments,然后为Filledillments创建了里程碑。

PS:这是我第一次发布到StackOverflow(我经常设法找到我的非常简单的问题的答案)所以请随时告诉我是否有任何我可以做的事情以便将来提出问题更加清晰。

2 个答案:

答案 0 :(得分:0)

尝试在工厂中明确定义类,以便它们不被猜到但是已知。

factory :user, class: User

factory :fulfillment, class: FulFillment

答案 1 :(得分:0)

事实证明我是个白痴。我有一个

validates :user, :presence

在我的 Milestone 模型上。难怪为什么它试图调用milestone.user

请忘记这件事。 ]: