如何使用相关工厂的特征?

时间:2015-09-08 18:15:47

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

我需要为相关模型编写测试。

规格/工厂/ users.rb的:

FactoryGirl.define do
  factory :user do
    sequence(:name){ |i| "us#{i}" }
    sequence(:email){ |i| "us#{i}@ad.ad" }
    password 'qwerty'
    password_confirmation{ |u| u.password } 
    info Faker::Lorem.paragraph(7)

    trait :user_status do
      status_id 0
    end

    trait :manager_status do
      status_id 1
    end

    trait :admin_status do
      status_id 2
    end    
  end 
end

但文件spec / factories / users.rb为空。

模式:

create_table "statuses", force: :cascade do |t|
  t.string "title"
end

create_table "users", force: :cascade do |t|
  t.string   "email",                  default: "", null: false
  t.string   "encrypted_password",     default: "", null: false
  t.integer  "status_id",              default: 0
  t.string   "name"  
end

页面index.html.erb包含以下代码:

....
...
<div class="status"><%= user.status.title if user.status_id %></div>
....
..

当我进行测试时:

it 'check response status code for index page' do
  visit users_path
  expect(response).to be_success 
end 

控制台显示以下错误消息:

 Failure/Error: visit users_path
 ActionView::Template::Error:
   undefined method `title' for nil:NilClass

如何使用特征为“用户”和“状态”编写工厂?

2 个答案:

答案 0 :(得分:3)

eirikir的解决方案非常接近,但Status仍然没有标题。

试试这个:

<强>规格/工厂/ users.rb的

FactoryGirl.define do
  factory :user do
    sequence(:name){ |i| "us#{i}" }
    sequence(:email){ |i| "us#{i}@ad.ad" }
    password 'qwerty'
    password_confirmation{ |u| u.password } 
    info Faker::Lorem.paragraph(7)

    trait :regular do
      association :status, factory: :user_status
    end

    trait :manager do
      association :status, factory: :manager_status
    end

    trait :admin do
      association :status, factory: :admin_status
    end    
  end 
end

<强>规格/工厂/ statuses.rb

FactoryGirl.define do
  factory :user_status, class: Status do
    title 'User'
  end

  factory :manager_status, class: Status do
    title 'Manager'
  end

  factory :admin_status, class: Status do
    title 'Admin'
  end
end

在您的规范中,创建User

create(:user, :regular)
create(:user, :manager)
create(:user, :admin)

build(:user, :regular)
build(:user, :manager)
build(:user, :admin)

等。

希望有所帮助!

答案 1 :(得分:0)

我会确保在构建之后存在关联的Status实例,例如:

trait :user_status do
  status_id 0

  after :build do
    FactoryGirl.create(:status, id: 0) unless Status.exists?(id: 0)
  end
end

您还可以概括Status实例的创建:

trait :user_status do
  status_id 0
end

trait :manager_status do
  status_id 1
end

trait :admin_status do
  status_id 2
end

after :build do |user|
  if user.status_id && !Status.exists?(id: user.status_id)
    FactoryGirl.create :status, id: user.status_id
  end
end