Rspec 2.14,FactoryGirl 4.2,Rails 3.2.11 - has_many through

时间:2013-10-26 02:44:23

标签: ruby-on-rails unit-testing rspec factory-bot

我是FactoryGirl的新手(并进行一般测试),我正在尝试为has_many关系建立一个工厂。到目前为止我发现的所有例子都使用了旧版本的工厂女孩​​,官方文档也没那么有用。

当我进行测试时,它说:

Failures:

  1) Brand has a valid factory
     Failure/Error: FactoryGirl.create(:brand).should be_valid
     ActiveRecord::RecordInvalid:
       Validation failed: Styles can't be blank
     # ./spec/models/brand_spec.rb:5:in `block (2 levels) in <top (required)>'

brand.rb

class Brand < ActiveRecord::Base
  attr_accessible               :title,
                                :style_ids

  has_many                      :brand_styles, dependent: :destroy
  has_many                      :styles,       through: :brand_styles

  validates_presence_of         :title
  validates_presence_of         :styles
end

style.rb

class Style < ActiveRecord::Base
  attr_accessible               :title

  has_many                      :brand_styles, dependent: :destroy
  has_many                      :brands,       through: :brand_styles

  validates_presence_of         :title
end

brand_style.rb

class BrandStyle < ActiveRecord::Base
  attr_accessible :brand_id, 
                  :style_id

  belongs_to      :brand
  belongs_to      :style
end

工厂

FactoryGirl.define do
  factory :brand do
    title "Some Brand"

    after(:create) do |brand| 
      brand.style create(:brand_style, brand:brand, style: FactoryGirl.build(:style))
      brand.reload
    end
  end

  factory :style do
    title "Some Style"
  end

  factory :brand_style do
    brand
    style
  end
end

规范

require 'spec_helper'

describe Brand do
  it "has a valid factory" do
    FactoryGirl.create(:brand).should be_valid
  end
end

--- --- EDIT

我根据Damien Roches的建议修改了我的工厂,现在我收到了这个错误:

Failures:

  1) Brand has a valid factory
     Failure/Error: FactoryGirl.create(:brand).should be_valid
     NoMethodError:
       undefined method `primary_key' for #<FactoryGirl::Declaration::Implicit:0x007fc581b2d178>
     # ./spec/factories/brand.rb:4:in `block (3 levels) in <top (required)>'
     # ./spec/models/brand_spec.rb:5:in `block (2 levels) in <top (required)>'

修改工厂

FactoryGirl.define do
  factory :brand do |brand|
    brand.title "Some Brand"
    brand.styles { build_list(:brand_style, 1, brand: brand, style: build(:style)) }
  end

  factory :style do
    title "Some Style"
  end

  factory :brand_style do
    brand
    style
  end
end

1 个答案:

答案 0 :(得分:0)

after(:create)块替换为:

styles { build_list(:brand_style, 1, brand: brand, style: build(:style)) }

我的factory_girl知识有点粗糙,所以如果你有进一步的麻烦请告诉我,当我有机会时我会回复。

几个笔记。您无法使用after(:create),因为您的brand模型需要styles。您无法使用brand.style,因为关系为has_many。那应该是brand.styles。这样,您就无法使用brand.styles = create(),因为赋值需要一个数组。您可以使用brand.styles = [create()],但我更喜欢create_list

我已将create(:brand_style)替换为build。测试不同的变体,因为我发现有时根据您的配置保存父对象时关联不会保存。有关详细信息,请参阅here