使用 rspec 测试字段在 Rails 模型中的唯一性验证,无需辅助 gem



我正在尝试编写测试来验证RoR模型中字段的唯一性。

我正在开发Ruby on Rails应用程序,我用它来练习TDD技能。到目前为止,我一直使用互联网作为我的资源。我正在编写有关模型验证的测试。我不会使用"应该"、"工厂女孩"(等)宝石。 我知道使用这些宝石可以节省很多编码时间,但我最终会使用这些宝石。我想学习如何在没有 gems 的情况下自己编写 rspec 测试,以帮助我了解如何编写测试。到目前为止,在"唯一性"测试之前,我做得很好。

如何在不使用"应该"、"工厂女孩"(等)宝石的情况下创建测试来验证"用户"模型中"电子邮件"字段的唯一性。 我知道使用这些宝石可以节省大量编码,但我最终会使用这些宝石。我想学习如何在没有 gems 的情况下自己编写 rspec 测试,以帮助我了解如何编写测试。

在 Stackoverflow(以及网络上的其他地方)上,这个问题的大多数"答案"都包括使用这些辅助宝石。但是,如果没有宝石,就找不到答案。

这是模型,User.rb```

class User < ApplicationRecord
validate: :name, :email, presence: true
validates :name, length: { minimum: 2 }
validates :name, length: { maximum: 50 }
# validates_format_of :email, with: /A([^@s]+)@((?:[-a-z0-9]+.)+[a-z]{2,})Z/i
validates :email, format: { with: /A([^@s]+)@((?:[-a-z0-9]+.)+[a-z]{2,})z/i, on: :create }
validates :email, uniqueness: true
end

And here is `user_spec.rb`.

require 'rails_helper'
RSpec.describe User, type: :model do
subject {
described_class.new(name: 'John', email: 'john@home.xyz')
}
describe 'Validation' do
it 'is valid with valid attributes' do
expect(subject).to be_valid
end
it 'is not valid without name' do
subject.name = nil
expect(subject).to_not be_valid
end
it 'is not valid without email' do
subject.email = nil
expect(subject).to_not be_valid
end
(...)
it 'is invalid if the email is not unique' do
expect(????????).to_not be_valid
end
end
end

'''

如何编写以测试唯一性。我应该使用"受试者"以外的其他东西来测试吗?请记住,这次我不想要使用宝石(应该/工厂女孩/等)的解决方案。

过去几天我一直在做这件事,但没有运气。有什么解决办法吗? Ruby on Rails上关于rspec的最佳教程在哪里?

要测试唯一性,首先您必须使用与subject中使用的相同电子邮件创建一个用户。然后,由于电子邮件的唯一性验证,您的subject将无效。

像这样:

before { described_class.create!(name: 'foo', email: 'john@home.xyz') }
it 'is invalid if the email is not unique' do
expect(subject).to be_invalid
end

好的,我让它工作了。 好的,在@Jagdeep辛格的建议下,我写了这个测试:

'''

context 'when email is not unique' do
before { described_class.create!(name: 'foo', email: 'john@home.xyz') }
it {expect(subject).to be_invalid}
end

context 'when email is unique' do
before { described_class.create!(name: 'foo', email: 'jane@home.xyz') }
it {expect(subject).to be_valid}
end

''' 而且似乎通过了测试。我添加了其他测试来测试有效的唯一性。 感谢您的帮助。

我决定重写整个测试以利用context使其更加清晰和可读。 这是我的重写:

# frozen_string_literal: true
require 'rails_helper'
RSpec.describe User, type: :model do
subject {
described_class.new(name: 'John', email: 'john@home.xyz')
}
describe '.validation' do

context 'when email is not unique' do
before { described_class.create!(name: 'foo', email: 'john@home.xyz') }
it {expect(subject).to be_invalid}
end
context 'when email is  unique' do
before { described_class.create!(name: 'foo', email: 'jane@home.xyz') }
it {expect(subject).to be_valid}
end
end
end