【问题标题】:User update test fails when more users present当更多用户出现时,用户更新测试失败
【发布时间】:2017-07-20 10:37:08
【问题描述】:

通过第 10 章中的教程,一切正常,并且测试绿色没有问题。但是,当我按照 清单 10.47 添加更多用户时,“使用友好转发更新用户”测试开始失败。

 FAIL["test_successful_edit_with_friendly_forwarding", UsersEditTest, 1.8292690003290772]
 test_successful_edit_with_friendly_forwarding#UsersEditTest (1.83s)
        Expected response to be a redirect to <http://www.example.com/users/762146111> but was a redirect to <http://www.example.com/users/14035331>.
        Expected "http://www.example.com/users/762146111" to be === "http://www.example.com/users/14035331".
        test/integration/users_edit_test.rb:35:in `block in <class:UsersEditTest>'

我已经对此进行了相当多的测试,当我从 users.yml 中删除用户时,测试再次通过。所以我的代码中有一个错误,只有当应用程序中有超过 2 个用户时才会出现。这是我的测试:

users_edit_test.rb

require 'test_helper'

class UsersEditTest < ActionDispatch::IntegrationTest

  def setup
    @user = users(:michael)
  end

  test 'unsuccessful edit' do
    log_in_as(@user)
    get edit_user_path(@user)
    assert_template 'users/edit'
    patch user_path(@user), params: { user: { name: '',
                                              email: 'foo@invalid',
                                              password:              'foo',
                                              password_confirmation: 'bar' } }
    assert_template 'users/edit'
    assert_select 'div.alert',
                  'The form contains 4 errors.'
  end

  # This is the failing test
  test "successful edit with friendly forwarding" do
    get edit_user_path(@user)
    log_in_as(@user)
    assert_redirected_to edit_user_url(@user)
    name  = "Foo Bar"
    email = "foo@bar.com"
    patch user_path(@user), params: { user: { name:  name,
                                              email: email,
                                              password:              "",
                                              password_confirmation: "" } }
    assert_not flash.empty?
    assert_redirected_to @user #The test is failing on this line
    @user.reload
    assert_equal name,  @user.name
    assert_equal email, @user.email
  end
end

查看错误,user_path(@user) 似乎返回了错误的用户。我已经测试过,看起来补丁请求失败,并且用户名和电子邮件是原始用户名和密码,而不是补丁请求中设置的。这可能是因为它正在修补错误的用户,但我不明白为什么或如何。当我测试找出@user 的值时,它总是解析为users.yml 中的第一个用户,据我所知。

users.yml

michael:
  name: Michael Example
  email: michael@example.com
  password_digest: <%= User.digest('password') %>
  admin: true

archer:
  name: Sterling Archer
  email: duchess@example.gov
  password_digest: <%= User.digest('password') %>

lana:
  name: Lana Kane
  email: hands@example.gov
  password_digest: <%= User.digest('password') %>

malory:
  name: Malory Archer
  email: boss@example.gov
  password_digest: <%= User.digest('password') %>

<% 30.times do |n| %>
user_<%= n %>:
  name:  <%= "User #{n}" %>
  email: <%= "user-#{n}@example.com" %>
  password_digest: <%= User.digest('password') %>
<% end %>

如果我删除其他用户并只保留前两个用户,则测试现在通过。这是我写测试时我们所处的状态。现在,我的分页测试失败了,因为没有足够的用户进行分页。应该是这样的。

我对 Rails 相当陌生(教程和所有内容),尤其是测试新手。我已经尝试了各种技术来临时更改测试以找出问题所在,但老实说我无法追踪错误在哪里。我已经将我所有的代码与提供的代码进行了比较,没有发现任何拼写错误或错误,但肯定有问题。

奇怪的是,我根本无法在 Heroku 的开发或生产中复制该错误。就我作为用户和查看日志而言,该应用程序的行为应有尽有。但是测试仍然失败——我一定是在某个地方引入了一个错误。或者我的测试是错误的,但我看不出与教程中的代码有什么不同。

我见过类似的问题,例如this one,但据我测试,重定向问题是有效的。此外,如果我更改我的测试以取消重定向,并测试 only 用户更新,测试仍然失败。所以问题很可能出在我的用户更新方法上。

user_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 show
    @user = User.find(params[:id])
  end

  def new
    @user = User.new
  end

  def create
    @user = User.new(user_params)
    if @user.save
      log_in @user
      flash[:success] = 'Welcome to the Sample App!'
      redirect_to @user
    else
      render 'new'
    end
  end

  def edit
    @user = User.find_by(params[:user_id])
  end

  def update
    @user = User.find_by(params[:user_id])
    if @user.update_attributes(user_params)
      flash[:success] = 'Profile Updated'
      redirect_to @user
    else
      render 'edit'
    end
  end

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

  private

    def user_params
      params.require(:user).permit(:name, :email, :password,
                                   :password_confirmation)
    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 correct user.
    def correct_user
      @user = User.find(params[:id])
      redirect_to(root_url) unless current_user?(@user)
    end

    # Confirms an admin user.
    def admin_user
      redirect_to(root_url) unless current_user.admin?
    end
end

【问题讨论】:

    标签: ruby-on-rails ruby testing integration-testing railstutorial.org


    【解决方案1】:

    我的问题确实是我的用户更新方法。我使用find_by 方法来选择用户,而不是find

    这是固定用户更新方式:

      def update
        @user = User.find(params[:id]) # "find" method instead of "find_by"
        if @user.update_attributes(user_params)
          flash[:success] = "Profile updated"
          redirect_to @user
        else
          render 'edit'
        end
      end
    

    现在所有测试都正确通过了。

    【讨论】:

      【解决方案2】:

      您可以通过以下方式获取记录:

      @user = User.find_by_id(params[:user_id])
      

      @user = User.find(params[:user_id])
      

      @user = User.where(id: params[:user_id]).first
      

      【讨论】:

      • 是的。因为我使用的是find_by(params[:user_id]),所以我只向该方法传递了一个值,而它需要两个。大概find_by(id: params[:user_id]) 也可以。奇怪的是,当我只将一个值传递给方法时它没有引发错误。
      • @NickBarreto 是的,您将id 作为密钥传递。如果对您有帮助,请投票并接受我的回答。谢谢
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-29
      • 1970-01-01
      • 2015-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多