从rails 4升级后,users_controller_test出错

时间:2016-01-11 22:42:05

标签: ruby-on-rails minitest ruby-on-rails-5

我已经使用rails 4.x运行了mhartls's rails教程几次,只是为了好玩,我再次开始,但更新到rails 5.0.0.beta1。 我已经设法找到解决所有不兼容性的解决方案,直到第9章。具体来说,我无法对用户控制器上的销毁操作进行测试。我明白了:

ERROR["test_should_redirect_destroy_when_not_logged_in", UsersControllerTest, 1.489256506320089]
 test_should_redirect_destroy_when_not_logged_in#UsersControllerTest (1.49s)
URI::InvalidURIError:         URI::InvalidURIError: bad URI(is not URI?): http://www.example.com:80destroy
            test/controllers/users_controller_test.rb:49:in `block (2 levels) in <class:UsersControllerTest>'
            test/controllers/users_controller_test.rb:48:in `block in <class:UsersControllerTest>'

URI::InvalidURIError: bad URI(is not URI?): http://www.example.com:80destroy
    test/controllers/users_controller_test.rb:49:in `block (2 levels) in <class:UsersControllerTest>'
    test/controllers/users_controller_test.rb:48:in `block in <class:UsersControllerTest>'

bin/rails test test/controllers/users_controller_test.rb:47

我的控制器销毁行动:

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

我的测试:

test "should redirect destroy when logged in as a non-admin" do
  log_in_as(@other_user, integration_test: 'true')
  assert_no_difference 'User.count' do
    delete :destroy, params: { id: @user }
  end
  assert_redirected_to root_url
end

链接实际上有效,但测试失败。我可以通过添加如下路线来测试通过:delete 'delete_user' => 'users#destroy'并将测试更改为:delete delete_user_path params:{id: @user}但是,实际网站和测试使用不同的路线,所以我不会知道我是否可以相信这一点。如果我从用户resources: resources :users, except: :destroy中删除了destroy,那么页面链接不起作用,但测试仍然通过。我没有看到如何在页面链接上使用delete_user路由,似乎无法让用户#destroy route在测试中工作。我知道这不是集成测试,但是这种解决方法修复了其他几个问题。我稍后会重构,这样才有意义。

其他相关控制器代码:

before_action :logged_in_user, only: [:index, :edit, :update, :destroy]
before_action :correct_user,   only: [:edit, :update]
before_action :admin_user,     only: :destroy

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

Test Helper Code:

    # Logs in a test user. (I think all tests must be like integration)
def log_in_as(user, options = {})
  password    = options[:password]    || 'password'
  remember_me = options[:remember_me] || '1'
 # the next line is the work around for rails version >=5.1
  integration_test = options[:integration_test] || 'false'
  if integration_test == 'true'
    post login_path, params: { session: {  email: user.email,
                                password: password,
                                remember_me: remember_me }
                              }
  else
#      params[:session][:user_id] = user.id
#      session[:user_id] = user.id 
   controller.session[:user_id] = user.id
   # params[session[:user_id] ] = user.id 
  end
end

的Gemfile:

source 'https://rubygems.org'

ruby '2.3.0'
gem 'rails',                     '>= 5.0.0.beta1'
gem 'railties',                  '>= 5.0.0.beta1'
gem 'bcrypt',                    '>= 3.1.10'
gem 'faker',                     '>= 1.6.1'
gem 'carrierwave',               '>= 0.10.0'
gem 'mini_magick',               '>= 4.3.6'
gem 'fog',                       '>= 2.0.0.pre.0'
gem 'kaminari', :git => "git://github.com/amatsuda/kaminari.git", :branch => 'master'
gem 'kaminari-bootstrap',        '>= 3.0.1'
gem 'bootstrap-sass',            '>= 3.3.6'
gem 'sass-rails',                '>= 5.0.4'
gem 'uglifier',                  '>= 2.7.2'
gem 'coffee-rails',              '>= 4.1.1'
gem 'jquery-rails',              '>= 4.0.5'
gem 'therubyracer',              '>= 0.12.2'
gem 'turbolinks', github: 'rails/turbolinks'
gem 'jbuilder',                  '>= 2.4'
gem 'sdoc',                      '>= 0.4.1', group: :doc
gem 'net-ssh'

group :development, :test do
  gem 'sqlite3',                  '>= 1.3.11'
  gem 'byebug',                   '>= 8.2.1'
  gem 'spring',                   '>= 1.6.1'
end

group :development do
  gem 'web-console',              '>= 3.0.0'
end

group :test do
  gem 'minitest-reporters',       '>= 1.1.7'
  gem 'mini_backtrace',           '>= 0.1.3'
  gem 'guard',                    '>= 2.13.0'
  gem 'guard-minitest',           '>= 2.4.4'
  gem 'minitest',                 '>= 5.8.3'
  gem 'rails-controller-testing', '>= 0.0.3'
end

group :production do
  gem 'pg',                       '>= 0.18.4'
  gem 'rails_12factor',           '>= 0.0.3'
  gem 'puma',                     '>= 2.15.3'
end

# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', '>= 1.2015.7', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

2 个答案:

答案 0 :(得分:1)

正确的解决方案是替换:

delete :destroy, params: { id: @user }

with:

delete user_url(@user)

答案 1 :(得分:0)

似乎我当前的设置(请参阅gemfile等)令牌(:destroy,:user等)的处理方式与我以前的设置相同(如mhartl推荐),所以我使用的修复方法是替换所有在我的测试中使用命名路由的令牌(:用户变为user_path(@user)。销毁操作似乎没有默认的命名路由,所以我在routes.rb文件中添加了一个。

我可以通过添加这样的路线来通过测试:

delete 'delete_user' => 'users#destroy'  

将测试更改为:

delete delete_user_path params:{id: @user} 

然而,实际的站点和测试使用不同的路由来执行相同的操作,所以我不知道我是否可以相信这是最终的解决方案。

如果我从用户资源中删除destroy:

resources :users, except: :destroy 

然后页面链接不起作用,但测试仍然通过。我没有看到如何在页面链接上使用添加的'delete_user(@user)路由,我在尝试时不断找到用户,我似乎无法让用户#destroy action在测试中工作增加的路线。