简体   繁体   English

Rspec测试用于检查唯一性

[英]Rspec tests for checking uniqueness

Here is the rspec test to check the uniqueness of an email ( from http://ruby.railstutorial.org/chapters/modeling-users.html#code-validates_uniqueness_of_email_test ) 以下是检查电子邮件唯一性的rspec测试(来自http://ruby.railstutorial.org/chapters/modeling-users.html#code-validates_uniqueness_of_email_test

require 'spec_helper'

describe User do

  before do
    @user = User.new(name: "Example User", email: "user@example.com")
  end
  .
  .
  .
  describe "when email address is already taken" do
    before do
      user_with_same_email = @user.dup
      user_with_same_email.save
    end

    it { should_not be_valid }
  end
end

As the author mentioned, I added 正如作者所说,我补充道

class User < ActiveRecord::Base
  .
  .
  .
  validates :email, presence: true, format: { with: VALID_EMAIL_REGEX },
                    uniqueness: true
end

to my user model and the tests pass. 到我的用户模型和测试通过。

But @user hasn't yet been saved to the database(I can't find @user.save statement anywhere is the code.) so, user_with_same_email is already unique since there is no other user with the same email in the database . 但是@user还没有保存到数据库中(我找不到任何地方的@ user.save语句代码。)因此,user_with_same_email已经是唯一的,因为数据库中没有其他用户拥有相同的电子邮件。 Then how does it work? 那它是如何工作的?

I created something similar in the console. 我在控制台中创建了类似的东西。 user_with_same_email.valid? user_with_same_email.valid? returns false (with error "has already been taken"), but user_with_same_email.save still works. 返回false(错误“已经被占用”),但user_with_same_email.save仍然有效。 why? 为什么?

Here's the source code for the be_valid matcher: 这是be_valid匹配器的源代码

match do |actual|
  actual.valid?
end

As you can see, the matcher does not actually save the record, it just calls the method valid? 正如您所看到的,匹配器实际上并不保存记录,它只是调用方法valid? on the instance. 在实例上。 valid? checks whether validations will pass or not and if not, sets error messages on the instance. 检查验证是否通过,如果没有,则在实例上设置错误消息。

In the case above, you are first (successfully) saving a user with the same email ( user_with_same_email ), which works since no user with that email has actually been saved yet. 在上面的例子中,您是第一个(成功)使用相同的电子邮件( user_with_same_email )保存用户,这是有效的,因为没有用户已经实际保存了该电子邮件。 Then you're checking for validation errors on another user instance ( @user ) which has the same email, and that obviously fails even though you have not actually saved the duplicate record. 然后,您正在检查具有相同电子邮件的另一个用户实例( @user )上的验证错误,即使您实际上没有保存重复记录,这显然也会失败。

Regarding what you get in the console, the problem is likely that save does not return an error even if it fails. 关于你在控制台中看到,问题很可能是save即使失败不返回一个错误。 Try using save! 尝试使用save! instead. 代替。

You can use the shoulda-matchers gem. 你可以使用shoulda-matchers gem。

# spec/models/user_spec.rb
require 'spec_helper'

describe User, 'validations' do
  it { should validate_uniqueness_of(:email) }
  it { should validate_presence_of(:email) }
  it { should validate_format_of(:email).with_message(VALID_EMAIL_REGEX) }
end

Not positive about the last one, but it looks like it should work. 对最后一个没有肯定,但它看起来应该有效。

If you're using clearance, you can use the built-in email_validator functionality PR here 如果您正在使用许可,则可以在此处使用内置的email_validator功能PR

# app/models/user.rb
validates :email, presence: true, email: true

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM