为什么Rspec / Factory Girl会生成带有nil ID的对象?

时间:2015-10-29 19:47:44

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

这是我的问题:

  it "should return all relatives of a specific relation - e.g. 'sister'" do
    u1 = create(:user)
    ft = create(:family_tree, user: u1)
    relation = "sister"
    u2 = create(:user)
    ft2 = create(:family_tree, user: u2)
    membership = create(:membership, invited: u2, relation: relation, invited: u1, family_tree: ft)
    expect(u1.relatives(relation).first.user.email).to eq u2.email
  end

这些是各自的工厂:

用户

# == Schema Information
#
# Table name: users (truncated for brevity)
#
#  id                     :integer          not null, primary key
#  email                  :string(255)      default(""), not null
#  encrypted_password     :string(255)      default("")

FactoryGirl.define do
  factory :user do
    association :family_tree
    email { Faker::Internet.email }
    password "password123"
    password_confirmation "password123"
  end
end

家谱

# == Schema Information
#
# Table name: family_trees
#
#  id         :integer          not null, primary key
#  name       :string(255)
#  user_id    :integer
#  created_at :datetime
#  updated_at :datetime
#

FactoryGirl.define do
  factory :family_tree do
    name { Faker::Name.name }
  end
end

成员

# == Schema Information
#
# Table name: memberships
#
#  id                      :integer          not null, primary key
#  family_tree_id          :integer
#  user_id                 :integer
#  relation                :string(255)
#  member_id               :integer
#  invited_id              :integer

FactoryGirl.define do
  factory :membership do
    family_tree
    association :inviter, factory: :user
    association :invited, factory: :user
    relation { Faker::Lorem.word }
    member
  end
end

但是当我运行测试时,我会使用id=nil返回对象。

[7] pry(#<RSpec::ExampleGroups::User>)> u1
=> #<User id: nil, email: "sage.tromp@dubuquehauck.name", encrypted_password: "$2a$04$JfWM7TvH9CgQWdGDXXy9L.5Y7TmhNFacrImOxYHnzt/...", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil, created_at: "2015-10-29 19:31:49", updated_at: "2015-10-29 19:31:49", first_name: "Rowland", confirmation_token: nil, confirmed_at: "2015-10-29 19:31:47", confirmation_sent_at: nil, unconfirmed_email: nil, invitation_relation: "velit", avatar: nil, invitation_token: nil, invitation_created_at: nil, invitation_sent_at: nil, invitation_accepted_at: nil, invitation_limit: nil, invited_by_id: nil, invited_by_type: nil, invitations_count: 0, bio: "Aut qui non aut occaecati. Consequuntur eveniet do...", last_name: "Johnson", gender: 1>
[8] pry(#<RSpec::ExampleGroups::User>)> ft
=> #<FamilyTree id: nil, name: "Jadyn Volkman MD", user_id: 906, created_at: "2015-10-29 19:31:49", updated_at: "2015-10-29 19:31:49">
[9] pry(#<RSpec::ExampleGroups::User>)> relation
=> "sister"
[10] pry(#<RSpec::ExampleGroups::User>)> u2
=> #<User id: nil, email: "samantha.breitenberg@simonis.net", encrypted_password: "$2a$04$gtcqmNDq4NhuyvAZsZNrg.GxoBzOkiVbfANpdcLYSLD...", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil, created_at: "2015-10-29 19:31:49", updated_at: "2015-10-29 19:31:49", first_name: "Noah", confirmation_token: nil, confirmed_at: "2015-10-29 19:31:47", confirmation_sent_at: nil, unconfirmed_email: nil, invitation_relation: "unde", avatar: nil, invitation_token: nil, invitation_created_at: nil, invitation_sent_at: nil, invitation_accepted_at: nil, invitation_limit: nil, invited_by_id: nil, invited_by_type: nil, invitations_count: 0, bio: "Omnis sit asperiores aut. Iste omnis accusantium i...", last_name: "Pagac", gender: 1>
[11] pry(#<RSpec::ExampleGroups::User>)> ft2
=> #<FamilyTree id: nil, name: "Bridie Lang", user_id: 907, created_at: "2015-10-29 19:31:49", updated_at: "2015-10-29 19:31:49">
[12] pry(#<RSpec::ExampleGroups::User>)> membership
=> #<Membership id: 111, family_tree_id: 1220, user_id: 908, created_at: "2015-10-29 19:31:49", updated_at: "2015-10-29 19:31:49", relation: "sister", member_id: 129, connection_sent_at: nil, connection_responded_at: nil, connect_send_limit: nil, connect_times_sent: nil, connected: nil, connect_type: nil, request_status: nil, connection_removed_at: nil, invited_id: 906>

注意虽然关联似乎仍然有效,即使它返回一个对象为id=nil的记录,你可以在这里看到:

[13] pry(#<RSpec::ExampleGroups::User>)> membership.inviter
    => #<User id: nil, email: "nils.walter@bruen.name", encrypted_password: "$2a$04$RAbEyhoU/cvJu1lvDM0mNOb2.VSoCnR76qThkbjWJNU...", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil, created_at: "2015-10-29 19:31:49", updated_at: "2015-10-29 19:31:49", first_name: "Alyce", confirmation_token: nil, confirmed_at: "2015-10-29 19:31:47", confirmation_sent_at: nil, unconfirmed_email: nil, invitation_relation: "placeat", avatar: nil, invitation_token: nil, invitation_created_at: nil, invitation_sent_at: nil, invitation_accepted_at: nil, invitation_limit: nil, invited_by_id: nil, invited_by_type: nil, invitations_count: 0, bio: "Autem vitae aliquid dicta doloribus rerum atque. H...", last_name: "Metz", gender: 1>
[14] pry(#<RSpec::ExampleGroups::User>)> membership.invited
=> #<User id: nil, email: "sage.tromp@dubuquehauck.name", encrypted_password: "$2a$04$JfWM7TvH9CgQWdGDXXy9L.5Y7TmhNFacrImOxYHnzt/...", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil, created_at: "2015-10-29 19:31:49", updated_at: "2015-10-29 19:31:49", first_name: "Rowland", confirmation_token: nil, confirmed_at: "2015-10-29 19:31:47", confirmation_sent_at: nil, unconfirmed_email: nil, invitation_relation: "velit", avatar: nil, invitation_token: nil, invitation_created_at: nil, invitation_sent_at: nil, invitation_accepted_at: nil, invitation_limit: nil, invited_by_id: nil, invited_by_type: nil, invitations_count: 0, bio: "Aut qui non aut occaecati. Consequuntur eveniet do...", last_name: "Johnson", gender: 1>

导致这种情况的原因是什么?

修改1

这是我的spec/rails_helper.rb

# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV["RAILS_ENV"] ||= 'test'
require 'spec_helper'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'devise'
require 'capybara/rails'
Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }

ActiveRecord::Migration.maintain_test_schema!

RSpec.configure do |config|
  config.include FactoryGirl::Syntax::Methods
  config.include Devise::TestHelpers, type: :controller
  config.include SpecAuthentication, type: :controller
  config.use_transactional_fixtures = false
  config.infer_spec_type_from_file_location!

  config.before(:each) do
    DatabaseCleaner.strategy = :transaction
  end

  config.before(:each, :js => true) do
    DatabaseCleaner.strategy = :truncation
  end

  config.before(:each) do
    DatabaseCleaner.start
  end

  config.after(:each) do
    DatabaseCleaner.clean
  end
end

这是我的spec/spec_helper.rb

RSpec.configure do |config|
  config.expect_with :rspec do |expectations|
    expectations.include_chain_clauses_in_custom_matcher_descriptions = true
  end

  config.mock_with :rspec do |mocks|
    mocks.verify_partial_doubles = true
  end
end

1 个答案:

答案 0 :(得分:2)

如果使用FactoryGirl构建对象,它会在没有id的情况下实例化新模型,因为您没有在工厂中提供id定义。

当您创建新模型时,FactoryGirl会将此模型持久保存到数据库中,并且数据库将生成#id字段。

因此,如果您不想持久保存工厂,则应提供#id属性定义:

FactoryGirl.define do
  factory :user do
    sequence(:id) { |number| number } 
    association :family_tree
    email { Faker::Internet.email }
    password "password123"
    password_confirmation "password123"
  end
end