使用 rspec 不使用辅助宝石测试 Rails 模型中字段的唯一性验证

Testing the validation of uniqueness of the field in Rails's model using rspec without helper gems

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

我正在 Ruby 开发 Rails 应用程序,我用这些应用程序来练习我在 TDD 方面的技能。到目前为止,我一直使用 Internet 作为我的资源。我正在为 model.I 编写验证测试,不会使用 'shoulda'、'FactoryGirl'(等等)宝石。 我知道使用这些 gems 会节省我很多编码,但我最终会使用这些 gems。我想学习如何在没有宝石的情况下自己编写 rspec 测试,以帮助我了解如何编写测试。到目前为止,在 'uniqueness' 测试之前,我做得很好。

如何在不使用 'shoulda'、'FactoryGirl'(等)gem 的情况下创建测试以验证 'User' 模型中 'email' 字段的唯一性。 我知道使用这些 gems 会节省大量编码,但我最终会使用这些 gems。我想学习如何在没有宝石的情况下自己编写 rspec 测试,以帮助我了解如何编写测试。

关于 Whosebug(以及网络上其他地方)的大多数 'answer' 问题都包括使用这些助手 gem。但是没有宝石就找不到答案。

这是模型,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

```

我该如何编写来测试唯一性。我应该使用 'subject' 以外的其他东西来测试吗?请记住,这次我不想要使用 gems (Shoulda/FactoryGirl/etc) 的解决方案。

过去几天我一直在努力,但没有成功。任何解决方案? rspec 关于 Ruby 关于 Rails 的最佳教程在哪里?

要测试唯一性,首先您必须使用与 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 Singh 的建议下,我写了这个测试:

```

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