Ruby on rails 我是否正确使用工厂?

Ruby on rails 我是否正确使用工厂?,ruby-on-rails,ruby,testing,rspec,factory-bot,Ruby On Rails,Ruby,Testing,Rspec,Factory Bot,这是我当前的测试设置: # spec/factories.rb require 'factory_girl' FactoryGirl.define do # Roles factory :user_role, :class => Role do name 'User' end # Users factory :user, :class => User do sequence(:email) {|n| "email#{n}@example.co

这是我当前的测试设置:

# spec/factories.rb
require 'factory_girl'

FactoryGirl.define do
  # Roles

  factory :user_role, :class => Role do
    name 'User'
  end

  # Users
  factory :user, :class => User do
    sequence(:email) {|n| "email#{n}@example.com" }
    password 'password'
    password_confirmation 'password'
    name 'Yuri Userington'
    roles { |a| [a.association(:user_role)] }
  end

  # Instruments
  factory :instrument, :class => Instrument do
    title "Doobie Doo Instrument Title"
    is_valid true
    association :user, :factory => :user
  end

  # Sequences
  sequence :email do
    "email#{n}@factory.com"
  end

end

# spec/controllers/instruments_controller_spec.rb
require 'spec_helper'

describe InstrumentsController do

  before (:each) do
    @instrument = FactoryGirl.create(:instrument)
    @attr = FactoryGirl.attributes_for(:instrument)
    @user = FactoryGirl.create(:user)
  end

  describe "GET index" do
    it "assigns all instruments as @instruments" do
      instrument = Instrument.new(@attr)
      instrument.user = @user 
      instrument.save!
      get :index
      assigns(:instruments).should eq([instrument])
    end 
  end

end
结果是,当我运行测试时,我的输出中出现以下错误:

Failures:

  1) InstrumentsController GET index assigns all instruments as @instruments
     Failure/Error: @instrument = FactoryGirl.create(:instrument)
     ActiveRecord::RecordNotFound:
       Couldn't find Role with id=2
     # ./app/models/user.rb:21:in `assign_role_after_sign_up'
     # ./spec/controllers/instruments_controller_spec.rb:24:in `block (2 levels) in <top (required)>'
故障:
1) InstrumentsController获取索引将所有仪器指定为@instruments
失败/错误:@instrument=FactoryGirl.create(:instrument)
ActiveRecord::RecordNotFound:
找不到id为2的角色
#./app/models/user.rb:21:in“注册后分配角色”
#./spec/controller/instruments\u controller\u spec.rb:24:in'block(2级)in'
基于此,我的:用户工厂中的角色关联调用似乎没有被调用——我在这里做错了什么?我是不是用了一种完全错误的方式


谢谢

我遇到了类似的问题,我使用回调来分配如下角色:

Factory.define :user_with_admin_role, :parent => :user do |user|
  user.after_create {|instance| instance.roles << Factory(:admin_role) }
end
Factory.define:user_和_admin_角色,:parent=>:user do | user|
user.after_创建{| instance | instance.roles user do
顺序(:email){n}“email{n}@example.com”}
密码“password”
密码\u确认“密码”
名字‘尤里·尤林顿’

在创建{| user | user.roles之后,这里有很多话要说。将您的代码与下面的代码进行比较,看看删除了多少行或单词

FactoryGirl.define do
  # Sequences
  sequence :email do |n|
    "email#{n}@factory.com"
  end

  # Roles
  factory :user_role, :class => Role do
    name 'User'
  end

  # Users
  factory :user do
    email
    password 'password'
    password_confirmation 'password'
    name 'Yuri Userington'
    roles { |user| [Factory(:user_role)] } #many to many
   end

  # Instruments
  factory :instrument, :class => Instrument do
    title "Doobie Doo Instrument Title"
    is_valid true
    association :user #one-to-one or one-to-many
  end

end
在你的测试中:

describe InstrumentsController do

  before (:each) do
    @user = Factory(:user)
  end

  describe "GET index" do
    it "assigns all instruments as @instruments" do
      instrument = Factory(:instrument, :user => @user)
      get :index
      assigns(:instruments).should eq([instrument])
    end 
  end

end
此外:

  • 我个人更喜欢用模拟和存根测试控制器

  • 我使用
    let
    代替实例变量和
    before\u filter


谢谢!我可以看一个你如何用这个例子来组合你的实际测试的例子吗?例如
描述“获取索引”做
@SizzlePants,一个领先的例子。请看他的例子。你想进一步阐述你的观点吗?特别是“为什么”在您的两个偏好背后?另外,非常感谢您提供了详细的答案/代码示例。1)测试是关于隔离潜在问题的,所以我只在集成测试中使用真实对象。2)这里有很好的解释:3)感谢您通常在stackoverflow上的意思是+1:)关于这一点,
roles{| user |[Factory(:user_role)]}
将创建一个
用户角色
记录,即使您只是在创建一个
用户
。在创建后使用
回调不会这样做。两者都不是对的或错的,这完全取决于您打算如何使用工厂。这只是需要注意的一点。@apreading r.e.使用mock/stub代替工厂,have您找到了一种使测试代码可维护的方法吗?我发现我最终不得不删除许多方法,并且生成的测试很难阅读,这在一定程度上减轻了我的想法。也许我只需要将一些代码重构到我的模型中,只是想知道您是否有一个视图?当您测试一个期望结果的方法时,可以使用存根从其他对象读取。重新读取可能有点复杂,但值得付出痛苦。事实上,我有一个案例,我依赖一个工厂。有一天,我们决定更改工厂,许多测试中断,只是因为没有以前预期的数据。你必须找到你的快乐媒介:)
describe InstrumentsController do

  before (:each) do
    @user = Factory(:user)
  end

  describe "GET index" do
    it "assigns all instruments as @instruments" do
      instrument = Factory(:instrument, :user => @user)
      get :index
      assigns(:instruments).should eq([instrument])
    end 
  end

end