【问题标题】:Why does this specification not work as expected?为什么这个规范不能按预期工作?
【发布时间】:2014-02-16 18:42:07
【问题描述】:

我查看了堆栈溢出以寻找答案,发现一些人发布了类似问题但解决方案没有帮助。据我所知,我的代码完全正确。

我正在关注以下教程: http://ruby.railstutorial.org/chapters/modeling-users#code-validates_uniqueness_of_email_case_insensitive_test

 require 'spec_helper'

describe User do

  before { @user = User.new(name: "Example User", email: "user@example.com") }

  subject { @user }

  it { should respond_to(:name) }
  it { should respond_to(:email) }

  it { should be_valid }

  describe "when name is not present" do
    before { @user.name = " " }
    it { should_not be_valid }
  end

  describe "when email is not present" do
    before { @user.email = " " }
    it { should_not be_valid }
  end

  describe "when name is too long" do
    before { @user.name = "a" * 51 }
    it { should_not be_valid }
  end

  describe "when email format is invalid" do
    it "should be invalid" do
      addresses = %w[user@foo,com user_at_foo.org example.user@foo. foo@bar_baz.com foo@bar+baz.com]
      addresses.each do | invalid_address |
        @user.email = invalid_address
        expect(@user).not_to be_valid
      end
    end
  end

  describe "when email format is valid" do
    it "should be valid" do
      addresses = %w[user@foo.COM A_US-ER@f.b.org frst.lst@foo.jp a+b@baz.cn]
      addresses.each do | valid_address |
        @user.email = valid_address
        expect(@user).to be_valid
      end
    end
  end

  describe "when email address is already taken" do
    before do
      user_with_same_email = @user.dup
      user_with_same_email.email = @user.email.upcase
      user_with_same_email.save
    end
    #it "should not be valid" do
    #  expect(@user).not_to be_valid
    #end
    it { should_not be_valid }

  end


end

最后一个规范失败了。

我的用户验证是这样的:

class User < ActiveRecord::Base
  before_save { self.email = email.downcase }
  validates :name, presence: true, length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, presence: true, format: { with: VALID_EMAIL_REGEX }, uniqueness: { case_sensative: false }
end

我完美地遵循了本教程,但我似乎无法让此验证正常工作。我知道本教程有点旧,我可能会使用一些较新的 gem。我也知道这不是进行此类验证的最佳方法,但本教程一开始只是让它变得非常简单。这是怎么回事?

谢谢!


编辑: 没有错误。验证在应该成功时却失败了。

Failures:
1) User when email address is already taken should not be valid
Failure/Error: it { should_not be_valid }
expected #<User id: nil, name: "Example User", email: "user@example.com", created_at: nil, updated_at: nil> not to be valid
# ./spec/models/user_spec.rb:58:in `block (3 levels in <top (required)>'

Finished in 0.09887 seconds
1 example, 1 failure

再次编辑。 user_spec.rb 已完全粘贴在 quest 中。抱歉,我是 ruby​​ 的新手,并没有意识到可能需要什么来帮助解决问题。

【问题讨论】:

  • 可以把错误信息放上去吗?
  • 是没有达到预期,还是因为引发了异常而失败?
  • 你在哪里/如何设置主题?换句话说,规范中的“它”是什么?请注意,有问题的电子邮件不是大写的,所以除非你有一个回调/等小写,否则看起来你正在测试错误的东西。使用 -b 运行,然后调用 save!。
  • 奇怪的是你把邮件大写了,但是测试失败的邮件却是小写了。除此之外,您需要保存原始的@user,这样数据库中就会有一条记录来验证它。
  • @DaveNewton 问题更新了更多信息。

标签: ruby-on-rails ruby rspec


【解决方案1】:

如果您继续阅读教程,您会发现作者说测试仍未完成才能通过。这是因为当前的验证仍然区分大小写。

添加uniqueness: { case_sensitive: false } 使测试按预期通过

validates :email, presence: true, format: { with: VALID_EMAIL_REGEX },
                    uniqueness: { case_sensitive: false }

【讨论】:

  • 开枪!谢谢你,但我不小心粘贴了旧代码。我在发帖时正在修补它。我更新了问题以反映当前代码。
【解决方案2】:

我认为它自己解决了。也许有人可以解释刚刚发生的事情。我决定继续学习本教程并将gem 'bcrypt-ruby', '3.1.2' 添加到gemfile 中。然后我跑了bundle install

然后我尝试运行rspec spec/,它返回一个错误:

Migrations are pending; run 'bin/rake db:migrate RAILS_ENV=development' to resolve this issue.

但是当我运行rake db:migrate 时,什么也没发生。所以我用谷歌搜索发现this SO posta solution

我跑了:

rake test:prepare 
rake db:migrate

然后所有测试都通过了。

也许我的测试环境让我发疯了?我还是不知道刚刚发生了什么。

【讨论】:

    【解决方案3】:

    您可以在.save 之前添加user_with_same_email.valid? 并提供其输出,但我相信它会是true,因为:

    1. 您尚未更改id@user

    2. 你只是改变的大小写,但它也是有效的,所以“A@A.COM”和“a@a.com”是相同的,并且有效。

    3. #valid 返回true,因为:email 存在,具有良好的Regexp,并且仍然是唯一的。

    【讨论】:

      最近更新 更多