Rspec + Factory Girl第一个例子有效,第二个+没有

AnA*_*ice 2 rspec ruby-on-rails rspec2 ruby-on-rails-3 factory-bot

我有一个这样的规格:

require 'spec_helper'

describe IncomingMailsController do

  include Devise::TestHelpers

  before(:each) do
    @user = Factory.create(:user)
    @user1 = Factory.create(:user)
    @group = Factory(:group)
    @perm1 = Factory.create(:permission, :user => @user)
    @perm2 = Factory.create(:permission, :user => @user1)
  end

  it "xxxxx case 1" do
   ....
  end

  it "xxxxx case 2" do
   ....
  end
Run Code Online (Sandbox Code Playgroud)

第一个案例1,工作正常,但第二个案例失败:

Failure/Error: @perm1 = Factory.create(:permission, :user => @user)
     RuntimeError:
       Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id
     # ./spec/factories.rb:23
Run Code Online (Sandbox Code Playgroud)

每个块之前每次运行都是新鲜的吗?

factories.rb看起来像:

require 'factory_girl'

Factory.define :user do |f|
  f.sequence(:fname) { |n| "fname#{n}" }
  f.sequence(:lname) { |n| "lname#{n}" }
  f.sequence(:email) { |n| "email#{n}@google.com" }
  f.password               "password"
  f.password_confirmation { |u| u.password }
  f.invitation_code        "dmbsrv82811"
end

Factory.define :group do |f|
  f.name "myGroup"
  f.sequence(:private_email) { |n| "myGroup#{n}" }
end

Factory.define :permission do |f|
  f.role_id         1
  f.group_id do
    (Group.find_by_name('myGroup')).id
  end
  f.creator_id do
    (User.find_by_fname('fname1')).id
  end
end
Run Code Online (Sandbox Code Playgroud)

谢谢

luk*_*all 5

在factory.rb的第23行你有

(User.find_by_fname('fname1')).id
Run Code Online (Sandbox Code Playgroud)

这是硬编码找到的fname1.但是,您的工厂使用序列来定义fname:

f.sequence(:fname) { |n| "fname#{n}" }
Run Code Online (Sandbox Code Playgroud)

这意味着在第二个规范中,fname的值将是fname2,而不是fname1.这是因为序列不会在不同规格之间重置.

所有这一切都意味着,当你调用User.find_by_fname,它无法找到fname1(仅fname2)的用户,所以它返回nil,这就是为什么你会得到零误差的名为id.

- 编辑 -

您是否正在使用传递给权限工厂的用户属性执行任何操作(例如Factory.create(:permission, :user => @user))?如果没有,我会把它改成类似的东西

Factory.create(:permission, :creator => @user)
Run Code Online (Sandbox Code Playgroud)

注意:如果您没有将Permission#creator设置为与User的关联,则您需要执行此操作

Factory.create(:permission, :creator_id => @user.id)
Run Code Online (Sandbox Code Playgroud)

在类似的情况下,您可能希望更多地定义您的工厂

Factory.define :permission do |f|
  f.role_id         1
  f.association :group, :factory => :group
  f.association :creator, :factory => :user
end
Run Code Online (Sandbox Code Playgroud)

如果您的关联设置正确,则无需担心ID,关联会为您做正确的事情.