RSpec 测试不允许两个用户使用相同的电子邮件地址

Posted

技术标签:

【中文标题】RSpec 测试不允许两个用户使用相同的电子邮件地址【英文标题】:RSpec test for not allowing two users with the same email address 【发布时间】:2014-11-24 09:39:05 【问题描述】:

首先我应该提一下,我对 Rails 很陌生,这是我的第一个“严肃”项目,所以如果这是一个简单的问题,但我找不到答案,我深表歉意。

我在我的项目中使用 TDD,并使用 RSpec 编写模型测试,使用 FactoryGirl 创建模型,使用 Faker 为模型创建虚拟数据。一切都很顺利,直到我添加了一个测试以确保没有两个用户拥有相同的电子邮件地址。在我的User 模型中,我这样验证了它:

# /app/models/user.rb
validates :email, :password_reset_code, :auth_token, uniqueness: true

我的工厂使用 Faker 创建用户模型,如下所示:

# /spec/factories/users.rb
FactoryGirl.define do
  factory :user do
    email  Faker::Internet.email 
    password  Faker::Internet.password 
    password_reset_code  Faker::Lorem.word 
    auth_token  Faker::Lorem.word 
  end
end

我的user_spec.rb 测试如下:

# /spec/models/user_spec.rb
it "is invalid with a duplicate email" do
  user = FactoryGirl.create(:user)
  FactoryGirl.create(:user, email: user.email).should_not be_valid
end

在这里,我使用 FactoryGirl 使用来自 Faker 的虚拟值创建一个新模型,将其保存到数据库中,然后使用与第一个相同的电子邮件创建另一个模型。我希望 RSpec 告诉我这个测试通过了,因为 should_not be_valid 部分。但是当我运行测试时,我得到了这个输出:

Failures:

  1) User is invalid with a duplicate email
     Failure/Error: FactoryGirl.create(:user, email: user.email).should_not be_valid
     ActiveRecord::RecordInvalid:
       Validation failed: Email has already been taken
     # ./spec/models/user_spec.rb:19:in `block (2 levels) in <top (required)>'

因此,模型验证似乎引发了 RSpec 未捕获并用于通过测试的错误?我设法通过将测试更改为以下方式来解决它:

it "is invalid with a duplicate email" do
  begin
    user = FactoryGirl.create(:user)
    FactoryGirl.create(:user, email: user.email).should_not be_valid
  rescue
    false
  end
end

似乎可行,但我觉得这不是最好的方法。

编写此测试的正确方法是什么?

【问题讨论】:

我不确定它是否相关,但快速搜索给了我这个github.com/rspec/rspec-expectations/blob/master/Should.md 【参考方案1】:

我也遇到了这个问题。您遇到的错误是由于 create() 方法实际上保留了模型,然后在 DB 层(嗯,持久层)抛出 ActiveRecord::RecordInvalid。如果你想断言一个模型是否有效,你应该为你的第二个对象使用 build() 方法,然后询问它是否有效。你可以在这个post阅读它。

此外,如果您只是想测试模型上的各种验证,我写了一个快速而肮脏的 gem,您可以使用它来断言一些更基本的模型验证。您可以查看here。

希望对您有所帮助。

【讨论】:

仅供参考,如果您要使用我链接到的 gem,可以通过以下代码行测试唯一性:Record.field_uniqueness(FactoryGirl.create(:user), :email) 谢谢,将第二个 create 更改为 build,现在运行良好。那个宝石看起来很有用,我去看看:)【参考方案2】:

我会选择:

# /spec/models/user_spec.rb
describe 'validations' do

  context 'with a duplicate email' do
    let(:other_user)  FactoryGirl.create(:user) 
    let(:attributes)  FactoryGirl.attributes_for(:user) 

    subject(:user)    User.new(attributes.merge(email: user.email)) 

    it 'is not valid' do
      expect(user).to_not be_valid
    end
  end
end

【讨论】:

以上是关于RSpec 测试不允许两个用户使用相同的电子邮件地址的主要内容,如果未能解决你的问题,请参考以下文章

使用Rails Rspec进行测试 - 预期和得到的不匹配

用户池允许两个用户使用相同的电子邮件,尽管配置

如何使用 rspec 测试 mandrill api

Rspec 不显示邮件正文中的内容

如何使用 RSpec 测试电子邮件标头

RSpec 和测试 Devise 的邮件