当我在user_spec.rb上测试验证字段的唯一性时,'新记录上缺少密码摘要'

时间:2013-07-13 23:45:11

标签: ruby-on-rails rspec ruby-on-rails-4 shoulda

我已经在这几个小时里苦苦挣扎,我无法在任何地方找到答案。

基本上我正在使用shoulda为我的模型编写规范,并且由于某种原因,即使我的let工作正常并且实际应用程序工作正常(手动确认并使用请求规范),如果我包括:

it { expect(user).to validate_uniqueness_of :email }

在我的describe块中,我将收到以下错误:

1) User attributes should require case sensitive unique value for email
 Failure/Error: it { expect(user).to validate_uniqueness_of :email }
 RuntimeError:
   Password digest missing on new record
 # ./spec/models/user_spec.rb:14:in `block (3 levels) in <top (required)>'

我已经到了解决这个规范的问题让我退缩,这从来都不是一件好事,因为实施已经有效。

如果有人可以帮助我在这里会很棒,因为我真的不想开始跳过那些因为某些晦涩的原因而失败的测试,只是为了让事情发生变化。

我觉得好像rspec'忽略'调用has_secure_password来保存摘要的before方法,但我不确定。我只是假设,因为如果请求规范工作正常,这是做我不知道的事情。

我正在使用rails 4.0.0

以下是相关代码。我感谢任何帮助。感谢

user_spec.rb

require  'spec_helper'

describe User do

  let(:user) { 
    user = User.new(:email => 'example@example.com', 
                    :username => 'theo', 
                    :password => 'secretpass',
                    :password_confirmation => 'secretpass')}

  describe "attributes" do

    it { expect(user).to validate_presence_of :email } 
    it { expect(user).to validate_uniqueness_of :email }

    it { expect(user).to validate_presence_of :username }
    it { expect(user).to validate_uniqueness_of :username }

    it "saves are saved" do
      user.save!
      expect(user).to be_valid
    end

  end  


end

user.rb

class User < ActiveRecord::Base
  has_secure_password


  validates :email, :username, presence: true, uniqueness: true
  validates :password, presence: true, :on => :create


end

users_controller.rb

class UsersController < ApplicationController
  def index
  end

  def new
    @user = User.new
  end

  def create
    @user = User.new(user_params)

    if @user.save
      redirect_to root_path, :notice => 'You have successfully signed up.'
    else
      render 'new'
    end
  end

  private

  def user_params
    params.require(:user).permit(:email, :username, :password, :password_confirmation)
  end
end

3 个答案:

答案 0 :(得分:5)

请确保您的用户架构中存在 password_digest ,详情请参阅here

create_table “users”, force: true do |t|
    ……
    t.text     “password_digest”
    …..
end

如果它在您的开发中有效而不是测试,请检查您是否在测试环境中执行rake db:migration,我的意思是 RAILS_ENV =测试rake db:migrate


!!!已更新 - 与shouda-matchers gocha

相关

这似乎是shoulda-matchers的错误,因为当您执行此操作时,测试将通过:

it "should be validate uniq of email " do
    user.save
    expect(user).to validate_uniqueness_of :email
end

user.save之所以这样做是因为this ,否则它会为你创建一个记录,这将导致你得到的错误:

# https://github.com/thoughtbot/shoulda-matchers/blob/master/lib/shoulda/matchers/active_model/validate_uniqueness_of_matcher.rb#L126
 def create_record_in_database(options = {})
      if options[:nil_value]
        value = nil
      else
        value = "arbitrary_string"
      end

      @subject.class.new.tap do |instance|
        instance.send("#{@attribute}=", value)
        instance.save(:validate => false) # the error happens here, not in your code
      end
    end

首先,这可能是shouda-matchers的错误,虽然我没有时间弄清楚如何修复它,因为现在你可以使用这种方法作为解决方法,或者使用其他方法测试这个的方法。

希望它有所帮助:-)

答案 1 :(得分:0)

可能是本应匹配器中的一个错误,可能与此问题有关https://github.com/thoughtbot/shoulda-matchers/issues/290

干杯

答案 2 :(得分:0)

回答你的问题:https://github.com/thoughtbot/shoulda-matchers/issues/371

简而言之,这是潜在的问题:

  

似乎has_secure_password的Rails 4版本增加了一个   before_create以确保填写password_digest;然而,   Rails 3版本没有这个检查。