用户注册测试在M.Hartl的Rails教程中失败

我一直在关注M. Hartl的Rails教程,我遇到了一个问题。 当我从第10章开始,所有代码都正常工作,我的测试套件正在通过。 在第11章中,我到目前为止所做的就是创建一个新的分支。 我的文件都没有被修改过。 但不知何故,我的测试套件现在失败了。 更奇怪的是,它不会100%失败。 有时它会通过,但大部分时间都会失败(如果我一次又一次地运行它而不更改任何代码)。 相关代码和错误消息如下。 任何帮助将非常感激。 谢谢

错误:

FAIL["test_valid_signup_information_with_account_activation", UsersSignupTest, 3.902866843] test_valid_signup_information_with_account_activation#UsersSignupTest (3.90s) Expected: 1 Actual: 2 test/integration/users_signup_test.rb:29:in `block in ' 

user_signup_test.rb

 require 'test_helper' class UsersSignupTest < ActionDispatch::IntegrationTest test "invalid signup information" do get signup_path assert_no_difference 'User.count' do post users_path, user: {name: "Stevan", email: "foo@invalid", password: "foo", password_confirmation: "bar"} end assert_template 'users/new' assert_select 'div#error_explanation' assert_select 'div.alert-danger' end test "valid signup information with account activation" do get signup_path #name = "Example User" #email = "user@example.com" #password = "password" assert_difference 'User.count', 1 do post users_path, user:{name: "Example User", email: "user@example.com", password: "password", password_confirmation: "password"} end assert_equal 1, ActionMailer::Base.deliveries.size user = assigns(:user) assert_not user.activated? # Try to log in before activation. log_in_as(user) assert_not is_logged_in? # Invalid activation token get edit_account_activation_path("invalid token") assert_not is_logged_in? # Valid token, wrong email get edit_account_activation_path(user.activation_token, email: 'wrong') assert_not is_logged_in? # Valid activation token get edit_account_activation_path(user.activation_token, email: user.email) assert user.reload.activated? follow_redirect! assert_template 'users/show' assert is_logged_in? end end 

users_controller.rb

 class UsersController  not editable in the browser end #before filters #confirms a logged-in user. def logged_in_user unless logged_in? store_location flash[:danger] = "Please log in." redirect_to login_url end end #confirms the currect user is the user currently logged in def correct_user @user = User.find(params[:id]) redirect_to(root_url) unless current_user?(@user) #@user==current_user refactored end #confirms as admin user def admin_user redirect_to(root_url) unless current_user.admin? end end 

user.rb

 class User < ActiveRecord::Base attr_accessor :remember_token, :activation_token, :reset_token before_save :downcase_email before_create :create_activation_digest validates(:name, presence:true , length: {maximum: 50}) VALID_EMAIL_REGEX = /\A[\w+\-.]+@[az\d\-]+(\.[az\d\-]+)*\.[az]{2,4}+\z/i validates(:email, presence:true, format: {with: VALID_EMAIL_REGEX}, uniqueness: {case_sensitive: false}) has_secure_password validates :password, length: {minimum: 6}, allow_blank: true #returns the hash digest of the given string def User.digest(string) #more idimatically correct to define as self.digest cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST : BCrypt::Engine.cost BCrypt::Password.create(string, cost: cost) end #returns a random token def User.new_token #more idiomatically correct to define as self.new_token SecureRandom.urlsafe_base64 end #remembers a user in the database for use in persistent sessions def remember self.remember_token = User.new_token update_attribute(:remember_digest, User.digest(remember_token)) end # Returns true if the given token matches the digest. def authenticated?(attribute, token) digest = send("#{attribute}_digest") return false if digest.nil? BCrypt::Password.new(digest).is_password?(token) end #forgets a user def forget update_attribute(:remember_digest, nil) end #activates an account def activate update_attribute(:activated, true) update_attribute(:activated_at, Time.zone.now) end #send activation email def send_activation_email UserMailer.account_activation(self).deliver end #sets the password reset attrobutes def create_reset_digest self.reset_token = User.new_token update_attribute(:reset_digest, User.digest(reset_token)) update_attribute(:reset_sent_at, Time.zone.now) end #sends password reset email def send_password_reset_email UserMailer.password_reset(self).deliver end #Returns true if password has expired def password_reset_expired? reset_sent_at < 2.hours.ago end private #converts email all to lower case def downcase_email self.email = email.downcase end #creates and assigns activation token and digest def create_activation_digest self.activation_token = User.new_token self.activation_digest = User.digest(activation_token) end end 

的Gemfile

 source 'https://rubygems.org' ruby '2.1.1' gem 'rails', '4.2.0.beta1' gem 'bcrypt', '3.1.7' gem 'faker', '1.4.2' gem 'will_paginate', '3.0.7' gem 'bootstrap-will_paginate','0.0.10' gem 'byebug', '3.5.1' gem 'bootstrap-sass', '3.2.0.0' gem 'sass-rails', '5.0.0.beta1' gem 'uglifier', '2.5.1' gem 'coffee-rails', '4.0.1' gem 'jquery-rails', '3.1.1' gem 'turbolinks', '2.3.0' gem 'jbuilder', '2.1.3' gem 'sdoc', '0.4.0', group: :doc group :test do gem 'minitest-reporters', '1.0.5' gem 'mini_backtrace', '0.1.3' gem 'guard-minitest', '2.3.1' end group :development do gem 'sqlite3', '1.3.9' gem 'spring', '1.1.3' end group :production do gem 'pg', '0.17.1' gem 'rails_12factor', '0.0.2' gem 'unicorn', '4.8.3' end 

您的代码缺少清单10.29中定义的setup方法。

在挂钩处理ActionMailer的所有规范之前,尝试添加以下内容

 before { ActionMailer::Base.deliveries = [] } 

它看起来像其他规格也发送电子邮件。 结果因规格的任意顺序而异。