[英]Ruby on Rails rspec uniqueness test failing inexplicably
I have a suite of test for my @user model (following mhartl's tutorial) but inexplicably my test for email uniqueness has started failing mysteriously 我有一个针对@user模型的测试套件(遵循mhartl的教程),但莫名其妙地,我对电子邮件唯一性的测试开始神秘地失败了
require 'spec_helper'
describe User do
before { @user = User.new(name: "Someguy", email: "some@guy.com",
password: "password", password_confirmation: "password")}
subject {@user}
it {should respond_to(:name)}
it {should respond_to(:email)}
it {should respond_to(:password_digest)}
it {should respond_to(:password)}
it {should respond_to(:password_confirmation)}
it {should respond_to(:remember_token)}
it {should respond_to(:authenticate)}
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 = "h"*50)}
it {should_not be_valid}
end
describe "when email format is invalid" do
it "should be invalid" do
addresses = %w[rubbishemail@foo,com rubbishuser_at_foo.org rubbish@user@.com]
addresses.each do |i|
@user.email = i
expect(@user).not_to be_valid
end
end
end
describe "when email format is valid" do
it "should be valid" do
addresses = %w[hi@iamhere.com yo@yothisisme.com whatup@whatupdog.co.uk]
addresses.each do |i|
@user.email = i
expect(@user).to be_valid
end
end
end
describe "when email is already taken" do
it "should_not be valid" 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
describe "when password is blank" do
before do
@user = User.new(name: "Example User", email: "user@example.com",
password: " ", password_confirmation: " ")
end
it { should_not be_valid }
end
describe "when password is not the same as password_confirmation" do
before {@user.password_confirmation = "mismatch"}
end
describe "with a password that's too short" do
before { @user.password = @user.password_confirmation = "a" * 5 }
it { should be_invalid }
end
describe "return value of authenticate method" do
before { @user.save }
let(:found_user) { User.find_by(email: @user.email) }
describe "with valid password" do
it { should eq found_user.authenticate(@user.password) }
end
describe "with invalid password" do
let(:user_for_invalid_password) { found_user.authenticate("invalid") }
it { should_not eq user_for_invalid_password }
specify { expect(user_for_invalid_password).to be_false }
end
end
end 结束
The specific test that is failing is: 失败的特定测试是:
describe "when email is already taken" do
it "should_not be valid" 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
And the error I am getting is as follows: 我得到的错误如下:
Failures:
1) User when email is already taken should not be valid
Failure/Error: it {should_not be_valid}
expected #<User id: nil, name: "Someguy", email: "some@guy.com", created_at: nil, updated_at: nil, password_digest: "$2a$04$ijkjuSSyFBAaMsDQ5vOyFO2VBVKFfFuvy5ArvfcWdW4H...", remember_token: nil> not to be valid
# ./spec/models/user_spec.rb:60:in `block (3 levels) in <top (required)>'
The problem doesn't seem to be with the user model itself since if I go to the console and try to manually reconstruct the test I get the expected result (user.valid? returns false after saving user.dup. 该问题似乎与用户模型本身无关,因为如果我转到控制台并尝试手动重建测试,则会得到预期的结果(user.valid?保存user.dup后返回false。
2.0.0-p247 :007 > user = User.new(name: "Someguy", email: "some@guy.com", password: "happiness", password_confirmation: "happiness")
=> #<User id: nil, name: "Someguy", email: "some@guy.com", created_at: nil, updated_at: nil, password_digest: "$2a$10$iGXz/r/RsiLKtNydXKft/en3KL.zT1B/bD5VehfNhiUj...", remember_token: nil>
2.0.0-p247 :008 > user2 = user.dup
=> #<User id: nil, name: "Someguy", email: "some@guy.com", created_at: nil, updated_at: nil, password_digest: "$2a$10$iGXz/r/RsiLKtNydXKft/en3KL.zT1B/bD5VehfNhiUj...", remember_token: nil>
2.0.0-p247 :009 > user2.save
(0.2ms) begin transaction
User Exists (0.2ms) SELECT 1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER('some@guy.com') LIMIT 1
Binary data inserted for `string` type on column `password_digest`
SQL (3.9ms) INSERT INTO "users" ("created_at", "email", "name", "password_digest", "updated_at") VALUES (?, ?, ?, ?, ?) [["created_at", Sun, 20 Oct 2013 00:30:45 UTC +00:00], ["email", "some@guy.com"], ["name", "Someguy"], ["password_digest", "$2a$10$iGXz/r/RsiLKtNydXKft/en3KL.zT1B/bD5VehfNhiUj0i2Xl0YiK"], ["updated_at", Sun, 20 Oct 2013 00:30:45 UTC +00:00]]
(2.2ms) commit transaction
=> true
2.0.0-p247 :010 > user.valid?
User Exists (0.4ms) SELECT 1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER('some@guy.com') LIMIT 1
=> false
2.0.0-p247 :011 >
The code for the user model is below (although I do not think this is the problem?) 用户模型的代码如下(尽管我不认为这是问题所在?)
class User < ActiveRecord::Base
before_save {self.email = email.downcase }
validates(:name, {presence: true, length: {maximum: 49}})
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates(:email, presence: true, format: {with: VALID_EMAIL_REGEX}, uniqueness: {case_sensitive: false})
validates :password, length: { minimum: 6 }
has_secure_password
end
I tried to identify where the test was failing by adding some puts into the test as follows 我尝试通过在测试中添加一些put来确定测试失败的地方
describe "when email is already taken" do
it "should_not be valid" do
user_with_same_email = @user.dup
puts @user.email+"hello"
user_with_same_email.email = @user.email.upcase
did_save = user_with_same_email.save
puts did_save
end
it {should_not be_valid}
end
and the result when running the test suite is: 运行测试套件时的结果是:
..........some@guy.comhello
true
.F........
Failures:
1) User when email is already taken should not be valid
Failure/Error: it {should_not be_valid}
expected #<User id: nil, name: "Someguy", email: "some@guy.com", created_at: nil, updated_at: nil, password_digest: "$2a$04$UKI8WbXbK9QnG7BF6AGnpeteaM8llDB/NMUj07UMTYsX...", remember_token: nil> not to be valid
# ./spec/models/user_spec.rb:62:in `block (3 levels) in <top (required)>'
Finished in 0.17485 seconds
20 examples, 1 failure
Failed examples:
rspec ./spec/models/user_spec.rb:62 # User when email is already taken should not be valid
from the above it looks as though the @user.email object is nil! 从上面看来,@ user.email对象似乎为nil! But this can't be the whole story because @user.dup is successfully assigning the correct values...
但这不是全部,因为@ user.dup成功分配了正确的值...
Can anyone explain why the test is failing? 谁能解释为什么测试失败?
THanks, 谢谢,
I think you need to use a before
block here as opposed to two it
blocks (the first block contains no test, and the second block will not have had the duplicate user saved before it is run). 我认为您需要
before
这里使用一个before
块,而不是两个it
块(第一个块不包含测试,第二个块在运行之前不会保存重复的用户)。
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.