0

我是测试新手,不知道为什么会失败:

我有一个测试

require 'spec_helper'
require 'cancan/matchers'

describe User do
  subject(:user) { User.create!(email: 'test@test.com', password: '12345678', password_confirmation: '12345678', goal_id: '1', experience_level_id: '1', gender: 'Female') }

it "should be valid with a name, goal, password, password_confirmation, experience_level, and gender" do
  user.should be_valid
end

我认为这应该通过。我可以通过站点前端创建用户,但收到以下失败消息:

1) User should be valid with a name, goal, password, password_confirmation, experience_level, and gender
     Failure/Error: subject(:user) { User.create!(email: 'test@test.com', password: '12345678', password_confirmation: '12345678', goal_id: '1', experience_level_id: '1', gender: 'Female') }
     RuntimeError:
       Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id
     # ./app/models/user.rb:32:in `add_initial_program'
     # ./spec/models/user_spec.rb:5:in `block (2 levels) in <top (required)>'
     # ./spec/models/user_spec.rb:13:in `block (2 levels) in <top (required)>'

编辑:

添加用户模型:

class User < ActiveRecord::Base

  devise :database_authenticatable, :registerable, :omniauthable,
         :recoverable, :rememberable, :trackable, :validatable, :token_authenticatable

  before_save :ensure_authentication_token

  attr_accessible :email, :password, :password_confirmation, :remember_me, :goal_id, :experience_level_id, :gender, :role, :name, :avatar, :remote_avatar_url, :authentication_token, :measurement_units

  validates :goal_id,                 presence: :true
  validates :experience_level_id, presence: :true 
  validates :gender,                    presence: :true

  before_create :add_initial_program, :assign_initial_settings

protected

  def add_initial_program
    prog_id = Program.for_user(self).first.id
    self.user_programs.build( :cycle_order => 1, :group_order => 1, :workout_order => 1, :program_id => prog_id)
  end

第 32 行是:prog_id = Program.for_user(self).first.id

和被引用的方法:

def self.for_user(user)
  where(:goal_id => user.goal_id, :experience_id => user.experience_level_id, :gender => user.gender)   
end
4

1 回答 1

1

prog_id = Program.for_user(self).first.id意思是,“获取与该用户关联的第一个程序的 id”。根据我们所看到的,我们可以推断出Program.for_user(self).first是 nil,并且该id方法正在这个 nil 上被调用。您确定在您的测试数据库中保存了一个与您在测试中创建的用户相关联的程序模型吗?您似乎没有在任何地方创建此模型,并且根据您的代码,在您尝试创建用户之前,必须有一个相关的程序。

编辑:

您可以像这样在主题块中初始化程序:

subject(:user) do 
    Program.create!(#whatever attributes are appropriate)
    User.create!(email: 'test@test.com', password: '12345678', password_confirmation: '12345678', goal_id: '1', experience_level_id: '1', gender: 'Female')
end

块中的最后一个值是主题块的相关返回值,所以只要块返回一个用户模型,事情应该没问题,即使你在块中有多个语句。对我来说,这是您可以单独更改测试的最干净的初始化选项,因为很明显用户和程序紧密结合在一起,因此要拥有有效的用户,您首先必须拥有关联的程序。我确实认为在 User 模型中包含创建程序的逻辑会更好,如果一个程序不存在(您可能想查看查询方法#first_or_create),但块内的多个语句现在应该可以工作。

于 2013-08-09T19:34:11.783 回答