ruby 用于检查唯一性的Rspec测试

to94eoyn  于 2023-03-08  发布在  Ruby
关注(0)|答案(3)|浏览(139)

下面是检查电子邮件唯一性的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

正如作者提到的,我补充说

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

到我的用户模型,测试通过。
但是@user还没有被保存到数据库中(我在代码中找不到@user.save语句),所以user_with_same_email已经是唯一的,因为在数据库中没有其他用户使用相同的电子邮件。那么它是如何工作的?
我在控制台中创建了类似的东西。user_with_same_email.valid?返回false(错误“已经被占用”),但是user_with_same_email.保存仍然可以工作。为什么?

1szpjjfi

1szpjjfi1#

您可以使用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

对最后一个不太肯定,但看起来应该能起作用。
如果使用clearance,则可以使用内置的email_validator功能PR here

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

az31mfrm2#

下面是be_valid匹配器的源代码:

match do |actual|
  actual.valid?
end

如您所见,匹配器实际上并不保存记录,它只是调用示例上的方法valid?valid?检查验证是否通过,如果没有通过,则在示例上设置错误消息。
在上面的例子中,您首先(成功地)保存了一个使用相同电子邮件的用户(user_with_same_email),这是因为实际上还没有使用该电子邮件的用户被 * 保存 *。然后您检查了另一个使用相同电子邮件的用户示例(@user)的验证错误,这显然是失败的,即使您实际上还没有保存重复的记录。
关于控制台中显示的内容,问题很可能是save即使失败也不返回错误,请尝试使用save!

5lwkijsr

5lwkijsr3#

别把东西弄乱了,把它拆成小块放轻松。
在下面找到如何测试检查唯一性的方法。

require 'spec_helper'

describe User do

  it "when email address is already taken" do
    User.create(name: "example" , email: "example@gmail.com") 
    check_new_user = "example@gmail.com"
    result = User.find_by_email(check_new_user).present? ? false : true

    expect(result).to be(true)

   #notice: this test will fails because check_new_user is already in the 
            database. you can set emails according to yours.
  end
end

相关问题