为什么我的模型的唯一性验证规范在应该通过时失败?

时间:2016-01-16 17:39:25

标签: ruby-on-rails ruby ruby-on-rails-4 rspec rspec-rails

我正在学习使用RSpec进行测试。有些东西不能用于我的测试。

我的模特:

class User < ActiveRecord::Base
  has_secure_password

  # Validation macros
  validates_presence_of :name, :email
  validates_uniqueness_of :email, case_sensitive: false
end

我的工厂:

FactoryGirl.define do
  factory :user do
    name "Joe Doe"
    email "joe@example.com"
    password_digest "super_secret_password"
  end
end

我的规格:

require 'rails_helper'

RSpec.describe User, type: :model do
  user = FactoryGirl.build(:user)

  it 'has a valid factory' do
    expect(FactoryGirl.build(:user)).to be_valid
  end

  it { is_expected.to respond_to(:name) }
  it { is_expected.to respond_to(:email) }
  it { is_expected.to respond_to(:password) }
  it { is_expected.to respond_to(:password_confirmation) }

  it { expect(user).to validate_presence_of(:name) }
  it { expect(user).to validate_presence_of(:email) }
  it { expect(user).to validate_presence_of(:password) }
  it { expect(user).to validate_uniqueness_of(:email).case_insensitive }
end

我希望这个测试通过。但是我得到了这个结果:

  

故障:

     

1)用户应验证:电子邮件不区分大小写        失败/错误:它{expect(user).to validate_uniqueness_of(:email).case_insensitive}

   User did not properly validate that :email is case-insensitively unique.
     The record you provided could not be created, as it failed with the
     following validation errors:

     * name: ["can't be blank"]
 # ./spec/models/user_spec.rb:18:in `block (2 levels) in <top (required)>'
     

以0.34066秒结束(文件加载1.56秒)9   例子,1失败

     

失败的例子:

     

rspec ./spec/models/user_spec.rb:18#用户应验证:电子邮件   不区分大小写

我缺少什么?

更新

我认为这是一个错误:https://github.com/thoughtbot/shoulda-matchers/issues/830

3 个答案:

答案 0 :(得分:0)

您的变量目前仅为所有测试设置一次

当您编写如下代码时:

RSpec.describe User, type: :model do
  user = FactoryGirl.build(:user)
end

每次运行新规范时,您都没有构建新用户。同样,使用#let是错误的方法,因为it memoizes the variable甚至在测试之间。相反,您需要使用RSpec before#each块。例如:

describe User do
  before do
    @user = FactoryGirl.build :user
  end

  # some specs
end

如果您有测试将用户持久存储到数据库,并且如果您在测试之间禁用了回滚或数据库清理,那么您定义的工厂(如当前编写的)肯定会失败唯一性验证。在这种情况下,您可能想尝试:

    在您的测试中
  • User.delete_all,或以其他方式在测试之间清理数据库。
  • 使用FactoryGirl sequencesFaker gem确保用户属性实际上是唯一的。

答案 1 :(得分:0)

USE let

TypeTag[List[Int]]
TypeTag[Int]
List(Int)

TypeTag[Any]
TypeTag[Nothing]
List()

答案 2 :(得分:0)

这是因为您将其声明为IMO的2倍!首先建立用户,然后在expect()内部建立相同的用户。

只需使用您用Factory-bot构建的第一个用户,就像这样:

it 'has a valid factory' do
    expect(user).to be_valid
end

P.S 最好使用Faker gem,而不要像factory.rb

中那样使用经过编码的实例