Rails:Rspec 和 FactoryGirl 协会

Rails: Rspec and FactoryGirl Associations

我正在尝试为我的控制器编写测试,一切都很顺利,直到我尝试为关联模型(has_many、belongs_to 等...)编写测试,我已经尝试阅读FactoryGirl 关于关联的入门指南,我已尽力遵循,但我收到如下错误:

1) GuestsController POST #create with valid attributes saves the guest to the database
 Failure/Error: post :create, guest: FactoryGirl.attributes_for(@guest)
 ArgumentError:
   Factory not registered: #<Guest:0x007fb7b1171298>

非常 rails 和测试新手。到目前为止,这是我得到的:

invites_controller:

...
has_many :guests
...

guests_controller:

....
belongs_to :invite
...

邀请工厂:

FactoryGirl.define do
  factory :invite do |f|
    f.name { Faker::Name.name }
    f.invite_code { Faker::Number.number(4) }

    factory :invite_with_guests do
      transient do
        guests_count 5
      end

      after(:create) do |invite, evaluator|
        create_list(:guest, evaluator.guests_count, invite: invite)
      end
   end
 end
end

客人工厂:

FactoryGirl.define do 
  factory :guest do |f|
    f.name { Faker::Name.name }
    f.attendance_status "yes"
    f.starter "Mushroom"
    f.main "Beef"
    f.dessert "Chicken"
    f.dietary_requirements { Faker::Lorem.words(4) }

    f.association :invite
  end
end

来宾控制器:

...
  def create
    @invite = Invite.find(params[:invite_id])
    @guest = @invite.guests.create(guest_params)
    redirect_to edit_invite_path(@invite)
  end
...

来宾控制器规格:

...
describe "POST #create" do
  before :each do
    @invite = FactoryGirl.create(:invite_with_guests)
    @guest = @invite.guests.first
  end

  context 'with valid attributes' do
    it 'saves the guest to the database' do
      expect {
        post :create, guest: FactoryGirl.attributes_for(@guest)
      }.to change(Guest,:count).by(1)
    end
  end

  ...
end
...

感谢所有帮助。

编辑:

路线:

           Prefix Verb   URI Pattern                                   Controller#Action
    invite_guests GET    /invites/:invite_id/guests(.:format)          guests#index
              POST   /invites/:invite_id/guests(.:format)          guests#create
 new_invite_guest GET    /invites/:invite_id/guests/new(.:format)      guests#new
edit_invite_guest GET    /invites/:invite_id/guests/:id/edit(.:format) guests#edit
     invite_guest GET    /invites/:invite_id/guests/:id(.:format)      guests#show
                  PATCH  /invites/:invite_id/guests/:id(.:format)      guests#update
                  PUT    /invites/:invite_id/guests/:id(.:format)      guests#update
                  DELETE /invites/:invite_id/guests/:id(.:format)      guests#destroy
   lookup_invites GET    /invites/lookup(.:format)                     invites#lookup
          invites GET    /invites(.:format)                            invites#index
                  POST   /invites(.:format)                            invites#create
       new_invite GET    /invites/new(.:format)                        invites#new
      edit_invite GET    /invites/:id/edit(.:format)                   invites#edit
           invite GET    /invites/:id(.:format)                        invites#show
                  PATCH  /invites/:id(.:format)                        invites#update
                  PUT    /invites/:id(.:format)                        invites#update
                  DELETE /invites/:id(.:format)                        invites#destroy
        dashboard GET    /dashboard(.:format)                          invites#index
             root GET    /                                             info#index

编辑 2:

我已经根据以下可能的答案更新了访客控制器规范,它仍然失败

...
describe "POST #create" do
  before :each do
    @invite = FactoryGirl.create(:invite_with_guests)
    @guest = @invite.guests.first
  end

  context 'with valid attributes' do
    it 'saves the guest to the database' do
      expect {
        post :create, guest: @guest.attributes
      }.to change(Guest,:count).by(1)
    end

    it 'redirects the edit invite path'
  end

...
end
...

我收到以下错误:

http://pastebin.com/WdyT6xtK

attributes_for 接受一个符号,即 returns 您可以用来构建对象的属性。

在你的情况下,你需要

expect {
  post :create, guest: @guest.attributes
}.to change(Guest,:count).by(1)

或定义guest_attributes

let(:guest_attributes){ attributes_for(:guest) }
let(:guest) { create(:guest, guest_attributes) )
...
# create an invite where the first guest is your defined guest

expect {
  post :create, guest: guest_attributes
}.to change(Guest,:count).by(1)

您已经定义了您的路线,以便客人嵌套在邀请下 - 因此当您 post 客人详细信息来创建客人时,您还需要提供它嵌套在其下的邀请,并将关联和。参见:

POST   /invites/:invite_id/guests(.:format)          guests#create

您的 create 操作也需要 invite_id。您也在控制器中使用 invite_id,因此必须提供它。

尝试:

post :create, invite_id: @invite.id, guest: @guest.attributes