使用问题的答案我将测试更改为以下测试正确并通过..
describe "when email is already taken" do
let(:user_with_same_email) { @user.dup }
before do
user_with_same_email.email.upcase!
user_with_same_email.save
end
it { user_with_same_email.should_not be_valid }
end
注意:不使用let(:user_with_same_email) { @user.dup }
会导致测试失败,因为如果它只是在user_with_same_email
块中重复,就像在此问题的所选答案中一样,它无法找到变量before
。
我有一个User
模型和一个user_spec.rb
测试文件,该文件对User
模型属性进行了各种验证。
以前我在user_spec.rb
文件的顶部写了以下内容来测试User
模型:
describe User do
before do
@user = User.new(name: "Example User", email: "user@example.com",
password: "foobar88", password_confirmation: "foobar88")
end
...
我想将此模型创建移至FactoryGirl
,因此我创建了一个factories.rb
文件:
FactoryGirl.define do
factory :user do
name "foo"
email { "#{name}@example.com" }
password "foobar99"
password_confirmation "foobar99"
end
end
然后我改变了我的user_spec.rb
:
describe User do
before do
@user = FactoryGirl.create(:user)
end
...
现在每个测试都像以前一样通过,除了一个:
describe "when email 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 }
end
现在除非`FactoryGirl正在跳过我的电子邮件唯一性验证,否则我无法弄清楚这里出了什么问题。
我的User
模型验证码:
class User < ActiveRecord::Base
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i unless const_defined?(:VALID_EMAIL_REGEX)
has_secure_password
attr_accessible :name, :email, :password, :password_confirmation
has_many :programs
before_save { self.email.downcase! }
validates :name, presence: true, length: { maximum: 50 }
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
答案 0 :(得分:3)
问题在于,当你说{should_not be_valid}时,RSpec会检查主题。在这种情况下,主题是User.new(你在顶部有“描述用户”,所以除非你指定别的东西,这是默认的。)
您想要检查user_with_same_email的有效性。
修改强> 试试这个,我认为它可能有用:
describe "when email 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 { @user_with_same_email.should_not be_valid }
end
答案 1 :(得分:2)
看起来你正在做(或引用)Michael Hartl的Rails Tutorial。这是我的代码看起来像你正在做什么,所以我希望它可以使用:
<强>规格/模型/ user_spec.rb 强>
describe User do
let(:user) { valid_user }
subject { user }
# ...
context "when email address is already taken" do
before { save_user(user) }
it { should_not be_valid }
end
# ...
end
spec / support / utilities.rb (创建特定用户)
def valid_user
User.new(name: "Example User",
email: "user@example.com",
password: "foobar",
password_confirmation: "foobar")
end
# ...
def save_user(user)
user_with_same_email = user.dup
user_with_same_email.email.upcase!
user_with_same_email.save
end
供参考: spec / factories.rb (仅创建任何旧的随机用户)
FactoryGirl.define do
factory :user do
sequence(:name) { |n| "Person #{n}" }
sequence(:email) { |n| "person_#{n}@example.com" }
password "foobar"
password_confirmation "foobar"
# ...
end
# ...
end
更新:在this StackOverflow answer找到您正在寻找同一问题的答案。我用我的代码测试了它,它对我有用。
更新2 :更改了我的代码,使用FactoryGirl.build
时,我需要用户,但不希望将其保存到数据库 。 This StackOverflow answer让我明白了。
<强>规格/模型/ user_spec.rb 强>
describe User do
let(:user) { FactoryGirl.create(:user) }
subject { user }
# ...
context "when email address is already taken" do
let(:user_with_same_email) do
FactoryGirl.build(:user, email: user.email)
end
subject { user_with_same_email }
before do
user_with_same_email.email.upcase!
user_with_same_email.save
end
it { should_not be_valid }
end
# ...
end
感谢您提出这个问题。给了我一些思考的东西,并在我自己的代码中做了一些重构。