从 rails 4 升级后 users_controller_test 出错
Error in users_controller_test after upgrading from rails 4
我 运行 通过 mhartls's rails 教程几次 rails 4.x 只是为了好玩,我又开始了,但更新到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
link 确实有效,但测试失败。我可以通过添加这样的路由来让测试通过:delete 'delete_user' => 'users#destroy'
并将测试更改为:delete delete_user_path params:{id: @user}
但是,实际站点和测试使用不同的路由,所以我不知道是否我可以相信这一点。如果我从用户 resources: resources :users, except: :destroy
中删除 destroy,那么页面 link 将不起作用,但测试仍然通过。我看不到如何在页面 link 上使用 delete_user 路由,并且似乎无法让 user#destroy 路由在测试中工作。我知道这不是集成测试,但此解决方法解决了其他几个问题。稍后我会重构,这样它就有意义了。
附加相关控制器代码:
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
宝石文件:
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]
似乎我在当前设置中(参见 gemfile 等)令牌(:destroy、:user 等)的处理方式与我以前的设置(如 mhartl 推荐的)不同,所以我使用的修复方法是用命名路由替换我测试中的所有标记(:user 变成 user_path(@user)。销毁操作似乎没有默认命名路由,所以我在 routes.rb 文件中添加了一个.
我可以通过添加这样的路由来让测试通过:
delete 'delete_user' => 'users#destroy'
并将测试更改为:
delete delete_user_path params:{id: @user}
但是,实际站点和测试对同一操作使用不同的路由,所以我不知道我是否可以相信这是最终解决方案。
如果我从用户资源中删除销毁:
resources :users, except: :destroy
然后页面 link 不工作,但测试仍然通过。我看不到如何在页面 link 上使用添加的 'delete_user(@user) route',我尝试时一直找不到用户,而且我似乎无法让 user#destroy 操作在测试中起作用没有添加的路线。
正确的解决办法是替换为:
delete :destroy, params: { id: @user }
与:
delete user_url(@user)
我 运行 通过 mhartls's rails 教程几次 rails 4.x 只是为了好玩,我又开始了,但更新到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
link 确实有效,但测试失败。我可以通过添加这样的路由来让测试通过:delete 'delete_user' => 'users#destroy'
并将测试更改为:delete delete_user_path params:{id: @user}
但是,实际站点和测试使用不同的路由,所以我不知道是否我可以相信这一点。如果我从用户 resources: resources :users, except: :destroy
中删除 destroy,那么页面 link 将不起作用,但测试仍然通过。我看不到如何在页面 link 上使用 delete_user 路由,并且似乎无法让 user#destroy 路由在测试中工作。我知道这不是集成测试,但此解决方法解决了其他几个问题。稍后我会重构,这样它就有意义了。
附加相关控制器代码:
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
宝石文件:
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]
似乎我在当前设置中(参见 gemfile 等)令牌(:destroy、:user 等)的处理方式与我以前的设置(如 mhartl 推荐的)不同,所以我使用的修复方法是用命名路由替换我测试中的所有标记(:user 变成 user_path(@user)。销毁操作似乎没有默认命名路由,所以我在 routes.rb 文件中添加了一个.
我可以通过添加这样的路由来让测试通过:
delete 'delete_user' => 'users#destroy'
并将测试更改为:
delete delete_user_path params:{id: @user}
但是,实际站点和测试对同一操作使用不同的路由,所以我不知道我是否可以相信这是最终解决方案。
如果我从用户资源中删除销毁:
resources :users, except: :destroy
然后页面 link 不工作,但测试仍然通过。我看不到如何在页面 link 上使用添加的 'delete_user(@user) route',我尝试时一直找不到用户,而且我似乎无法让 user#destroy 操作在测试中起作用没有添加的路线。
正确的解决办法是替换为:
delete :destroy, params: { id: @user }
与:
delete user_url(@user)