无法通过shoulda匹配器获得唯一性验证测试通过

时间:2016-07-23 11:54:26

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

我的achievement_spec.rb中有一个shoulda匹配器,我无法通过:

规格:

- require 'rails_helper' 
   RSpec.describe Achievement, type: :model do  
   describe 'validations' do 
     it { should validate_presence_of(:title) }
     it { should validate_uniqueness_of(:title).case_insensitive.scoped_to(:user_id).with_message("you
   can't have two achievements with same title")}    
     it { should validate_presence_of(:user) } 
     it { should belong_to(:user) } 
end 
end

型号:

- class Achievement < ActiveRecord::Base    belongs_to :user

    validates :title, presence: true
    validates :user, presence: true     
    validates :title, uniqueness: {
        scope: :user_id,        
        message: "you can't have two achievements with the same title"  
}   

    enum privacy: [ :public_access, :private_access, :friends_access ]

     def description_html
       Redcarpet::Markdown.new(Redcarpet::Render::HTML).render(description) 
end
end

错误:

- .F..

   Failures:

     1) Achievement validations should validate that :title is
   case-sensitively unique within the scope of :user_id, producing a
   custom validation error on failure
        Failure/Error: it { should validate_uniqueness_of(:title).scoped_to(:user_id).with_message("you
   can't have two achievements with same title") }

          Achievement did not properly validate that :title is case-sensitively
          unique within the scope of :user_id, producing a custom validation error
          on failure.
            After taking the given Achievement, setting its :title to ‹"an
            arbitrary value"›, and saving it as the existing record, then making a
            new Achievement and setting its :title to ‹"an arbitrary value"› as
            well and its :user_id to a different value, ‹nil›, the matcher
            expected the new Achievement to be invalid and to produce the
            validation error "you can't have two achievements with same title" on
            :title. The record was indeed invalid, but it produced these
            validation errors instead:

            * user: ["can't be blank"]
            * title: ["you can't have two achievements with the same title"]
        # ./spec/models/achievement_spec.rb:29:in `block (3 levels) in <top (required)>'

   Finished in 0.16555 seconds (files took 3.13 seconds to load) 4
   examples, 1 failure

   Failed examples:

   rspec ./spec/models/achievement_spec.rb:29 # Achievement validations
   should validate that :title is case-sensitively unique within the
   scope of :user_id, producing a custom validation error on failure

   [Finished in 4.1s with exit code 1] [cmd: ['rspec', '-I
   /home/mayur/Downloads/MyWork/ruby/i-rock/spec/models',
   '/home/mayur/Downloads/MyWork/ruby/i-rock/spec/models/achievement_spec.rb']]
   [dir: /home/mayur/Downloads/MyWork/ruby/i-rock] [path:
   /usr/local/rvm/gems/ruby-2.2.4/bin:/usr/local/rvm/gems/ruby-2.2.4@global/bin:/usr/local/rvm/rubies/ruby-2.2.4/bin:/usr/lib64/qt-3.3/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/usr/local/rvm/bin:/home/mayur/.local/bin:/home/mayur/bin]

如何摆脱上述错误?

我尝试了以下解决方案,但得到了相同的错误:

模特改变:

validates :title, uniqueness: {
        case_sensitive: false,
        scope: :user_id, 
        message: "you can't have two achievements with the same title"
    }

规格变更:

it { should validate_uniqueness_of(:title).case_insensitive.scoped_to(:user_id).with_message("you can't have two achievements with same title") }

再次出错:

.F..

Failures:

  1) Achievement validations should validate that :title is case-insensitively unique within the scope of :user_id, producing a custom validation error on failure
     Failure/Error: it { should validate_uniqueness_of(:title).case_insensitive.scoped_to(:user_id).with_message("you can't have two achievements with same title") }

       Achievement did not properly validate that :title is case-insensitively
       unique within the scope of :user_id, producing a custom validation error
       on failure.
         After taking the given Achievement, setting its :title to ‹"an
         arbitrary value"›, and saving it as the existing record, then making a
         new Achievement and setting its :title to ‹"an arbitrary value"› as
         well and its :user_id to a different value, ‹nil›, the matcher
         expected the new Achievement to be invalid and to produce the
         validation error "you can't have two achievements with same title" on
         :title. The record was indeed invalid, but it produced these
         validation errors instead:

         * user: ["can't be blank"]
         * title: ["you can't have two achievements with the same title"]
     # ./spec/models/achievement_spec.rb:29:in `block (3 levels) in <top (required)>'

Finished in 0.13566 seconds (files took 3.14 seconds to load)
4 examples, 1 failure

Failed examples:

rspec ./spec/models/achievement_spec.rb:29 # Achievement validations should validate that :title is case-insensitively unique within the scope of :user_id, producing a custom validation error on failure

2 个答案:

答案 0 :(得分:0)

由于规范中定义的错误消息与模型中的错误消息不匹配,因此发生了故障。您在规范中缺少the一词:

规格

...  .with_message("you can't have two achievements with same title")}

型号

...  message: "you can't have two achievements with the same title"

.with_message上的唯一性验证消息中修复title中规范中定义的内容以与模型中定义的内容相匹配,应该可以解决故障。

答案 1 :(得分:-1)

您需要构建工厂并确保在运行这些验证之前有用户:

describe Achievment do
  context 'validations' do
    before { FactoryGirl.build(:achievement) }

    it do
      should validate_uniqueness_of(:title).
        scoped_to(:user_id).
        case_insensitive
    end
  end
end

你的工厂:

FactoryGirl.define do
  factory :achievement
    title 'some-string'
    user
  end
end