Rspec 3:格式正则表达式中断验证测试

时间:2015-04-02 02:31:39

标签: ruby-on-rails regex rspec factory-bot

我正在测试从头开始构建用户身份验证。

我从测试和设置验证开始,他们都通过了。一旦我添加了format: { with: ... }方法,我的测试套件就崩溃了。

以下是代码的失败:

Failures:

  1) User validations requires an email
     Failure/Error: expect(user).to validate_presence_of(:email)
     NoMethodError:
       undefined method `validate_presence_of' for #<RSpec::ExampleGroups::User::Validations:0x007fae7f5551b0>
     # ./spec/models/user_spec.rb:14:in `block (3 levels) in <top (required)>'

  2) User validations requires a unique email
     Failure/Error: expect(user).to validate_uniqueness_of(:email)
     NoMethodError:
       undefined method `validate_uniqueness_of' for #<RSpec::ExampleGroups::User::Validations:0x007fae83193b90>
     # ./spec/models/user_spec.rb:18:in `block (3 levels) in <top (required)>'

  3) User validations requires a unique email (case insensitive)
     Failure/Error: expect(user).to validate_uniqueness_of(:email)
     NoMethodError:
       undefined method `validate_uniqueness_of' for #<RSpec::ExampleGroups::User::Validations:0x007fae83168670>
     # ./spec/models/user_spec.rb:23:in `block (3 levels) in <top (required)>'

Finished in 0.04888 seconds (files took 1.2 seconds to load)
6 examples, 3 failures

规格/模型/ user_spec.rb

require 'rails_helper'

RSpec.describe User, :type => :model do
    let(:valid_attr) { attributes_for(:user) }

    context "validations" do
        let(:user) { User.new(valid_attr) }

        before do
            User.create(valid_attr)
        end

        it "requires an email" do
            expect(user).to validate_presence_of(:email)
        end

        it "requires a unique email" do
            expect(user).to validate_uniqueness_of(:email)
        end

        it "requires a unique email (case insensitive)" do
            user.email = "BROWN@DOGS.COM"
            expect(user).to validate_uniqueness_of(:email)
        end

        it "requires the email to look like an email" do
            user.email = "brown"
            expect(user).to_not be_valid
        end
    end

    describe "#downcase_email" do
        it "makes the email attribute lowercase" do
            user = User.new(valid_attr.merge(email: "YELLOW@DOGS.COM"))
            expect{ user.downcase_email }.to change{ user.email }.
                from("YELLOW@DOGS.COM").
                to("yellow@dogs.com")
        end

        it "downcases an email before saving" do
            user = build(:user)
            user.email = "BROWN@DOGS.COM"
            expect(user.save).to be true
            expect(user.email).to eq("brown@dogs.com")
        end
    end
end

工厂女孩 users.rb

FactoryGirl.define do
  factory :user do
    first_name "Charlie"
    last_name "Brown"
    email "brown@dogs.com"
    password "charbar1234"
    password_confirmation "charbar1234"
  end

end

模型/ user.rb

class User < ActiveRecord::Base
    has_secure_password
    validates :email, presence: true,
                      uniqueness: true,
                      format: {
                        with: /\A[A-Za-z0-9._%+-]+@[A-Za-z0-9\.-]+\.[A-Za-z]+\Z/
                      }

    before_save :downcase_email

    def downcase_email
        self.email = email.downcase
    end
end

2 个答案:

答案 0 :(得分:1)

Rspec可能会被这个额外的格式参数搞糊涂,因此无法正确动态创建validates_*_of方法。您可以将测试重写为更直接:

it "requires an email" do
  expect(user).to be_valid
  # other test on error message here perhaps?
end

或将格式部分放在自己的验证行上:

validates :email, presence: true, uniqueness: true
validates :email, format: {
                    with: /\A[A-Za-z0-9._%+-]+@[A-Za-z0-9\.-]+\.[A-Za-z]+\Z/
                  }

答案 1 :(得分:1)

更好的方法是使用URI对象:

validates_format_of :website_url, with: URI.regexp