User Signup Test failing in M.Hartl's Rails Tutorial

帅比萌擦擦* 提交于 2019-12-25 00:42:50

问题


I've been following M. Hartl's Rails Tutorial and I've encountered a problem. As I moved from chapter 10 all by code was working and my test suite was passing. In chapter 11, all I have done so far is to create a new branch. None of my files have been altered. Yet somehow, my test suite is now failing. Even more strange, is that it doesn't fail 100% of the time. Sometimes it passes, but most of the time it fails (if I run it again and again without changing any code). The relevant code and error message is below. Any help would be appreciated very much. Thanks

Error:

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 <class:UsersSignupTest>'

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 < ApplicationController
  before_action :logged_in_user, only: [:index, :edit, :update, :destroy]
  before_action :correct_user, only: [:edit, :update]
  before_action :admin_user, only: :destroy

  def index
    @users = User.paginate(page: params[:page])
  end

  def new
    @user = User.new
  end

  def show
    @user = User.find(params[:id])
  end

  def create
    @user = User.new(user_params)  
    if @user.save
      #UserMailer.account_activation(@user).deliver #deliver_now
      @user.send_activation_email
      flash[:info] = "Please check your email to activate your account"
      redirect_to root_url
    else
      render 'new'
    end
  end

  def destroy
    User.find(params[:id]).destroy
    flash[:success] = "User deleted"
    redirect_to users_url
  end

  def edit
    #@user = User.find(params[:id]) no longer needed as we have implemented correct_user
  end

  def update
    #@user = User.find(params[:id]) no longer needed as we have implemented correct_user
    if @user.update_attributes(user_params)
      flash[:success] = 'Profile updated'
      redirect_to @user
    else
      render 'edit'
    end
  end

  private 

    def user_params
      params.require(:user).permit(:name, :email, :password, :password_confirmation) #haven't permit admin -> 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+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]{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

回答1:


Your code is missing the setup method defined in Listing 10.29.




回答2:


Try to add the following before hook to all specs dealing with ActionMailer

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

It looks like other specs also send emails. Results vary because of arbitrary order of specs.



来源:https://stackoverflow.com/questions/27395083/user-signup-test-failing-in-m-hartls-rails-tutorial

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!