ruby-on-rails – RSpec测试破坏方法(Rails Tutorial 3.2 Ch.9,E
注意:我已经阅读了
this的问题和答案,但由于某些原因代码并不适合我. (见下面的错误我得到)
Rails教程第9章的练习10要求您:修改销毁动作[为用户],以防止管理员用户破坏自己. (首先写一个测试) 这里的棘手部分是测试它,因为应用程序已经隐藏了当前用户的“删除”链接,因此您必须直接执行http请求. 我得到了代码,并通过删除隐藏当前用户的删除链接的代码进行测试.果然,如果我点击当前登录的用户的删除链接,它会重定向我,并给我通知消息. 来自users_controller.rb def destroy @user = User.find(params[:id]) if current_user?(@user) redirect_to users_path,notice: "You can't destroy yourself." else @user.destroy flash[:success] = "User destroyed." redirect_to users_path end end 我遇到的问题是编写这个测试,发送删除请求并调用destroy方法.我试过Rspec test for destroy if no delete link的解决方案,我在这里复制: 来自user_pages_spec.rb describe "destroy" do let(:admin) { FactoryGirl.create(:admin) } it "should not allow the admin to delete herself" do sign_in admin #expect { delete user_path(admin),method: :delete }.should change(User,:count) expect { delete :destroy,:id => admin.id }.should_not change(User,:count) end end 但是当我运行这个,我从RSpec得到这个错误 Failures: 1) User Pages destroy should not allow the admin to delete herself Failure/Error: expect { delete :destroy,:count) ArgumentError: bad argument (expected URI object or URI string) # ./spec/requests/user_pages_spec.rb:180:in `block (4 levels) in <top (required)>' # ./spec/requests/user_pages_spec.rb:180:in `block (3 levels) in <top (required)>' 所以我的问题是: 环境: 宝石测试: 更多信息 it "should be able to delete another user" do expect { click_link('delete') }.to change(User,:count).by(-1) end 但是我没有尝试直接生成删除请求已经有效地调用了destroy方法. 谢谢你的帮助! 将 **更新** 我试过DVG的建议: describe "destroy" do let(:admin) { FactoryGirl.create(:admin) } it "should not allow the admin to delete herself" do sign_in admin #expect { delete user_path(admin),:id => admin }.to_not change(User,:count) end end 并得到这个错误: 6) User Pages destroy should not allow the admin to delete herself Failure/Error: expect { delete :destroy,:count) ArgumentError: bad argument (expected URI object or URI string) # ./spec/requests/user_pages_spec.rb:190:in `block (4 levels) in <top (required)>' # ./spec/requests/user_pages_spec.rb:190:in `block (3 levels) in <top (required)>' 解 我在FOREVER之后想到了. 我不得不使用Rack :: Test发出DELETE请求,但是Capybara和Rack :: Test不共享同一个MockSession,所以我不得不将:remember_token和:!sample_app_session cookie放入DELETE请求手动.这是有效的(下面列出的另一个问题是,我有一个force_ssl声明,不让我的摧毁行动被调用. describe "destroy" do let!(:admin) { FactoryGirl.create(:admin) } before do sign_in admin end it "should delete a normal user" do user = FactoryGirl.create(:user) expect { delete user_path(user),{},'HTTP_COOKIE' => "remember_token=#{admin.remember_token},#{Capybara.current_session.driver.response.headers["Set-Cookie"]}" }. to change(User,:count).by(-1) end it "should not allow the admin to delete herself" do expect { delete user_path(admin),#{Capybara.current_session.driver.response.headers["Set-Cookie"]}" }. to_not change(User,:count) end end 我在我的users_controller.rb中的before_filters之后有一个force_ssl语句,这是以某种方式抛出的东西,所以我没有得到摧毁动作. class UsersController < ApplicationController before_filter :signed_in_user,only: [:edit,:update,:index] before_filter :existing_user,only: [:new,:create] before_filter :correct_user,:update] before_filter :admin_user,only: :destroy #force_ssl def index @users = User.paginate(page: params[:page]) end def show @user = User.find(params[:id]) @microposts = @user.microposts.paginate(page: params[:page]) end def destroy @user = User.find(params[:id]) if current_user?(@user) redirect_to users_path,notice: "You can't destroy yourself." else @user.destroy flash[:success] = "User destroyed." redirect_to users_path end end 这些有助于解决问题 https://gist.github.com/484787 http://collectiveidea.com/blog/archives/2012/01/05/capybara-cucumber-and-how-the-cookie-crumbles/ 解决方法
您将混淆rspec-rails请求规范,这些规范是集成测试,并在模拟浏览器中执行,控制器分别指定哪个测试控制器. delete(action,* args)(以及获取,发布等) – 是一种模拟来自ActionController :: TestCase的请求的方法,因此在测试中不可用.
所以你唯一的选择是在浏览器中模拟一个点击.我不知道你如何隐藏你的删除链接,如果html在那里,但隐藏你应该能够点击它.如果不存在(生成视图时在服务器端删除),您可以使用capybara的page.execute_script(但是您必须为此示例启用javascript:js => true).您可以添加链接: page.execute_script("$('body').append("<a href="/users/1" data-method="delete" rel="nofollow">Destroy</a>")") 或进行ajax调用: page.execute_script("$.ajax({type:'DELETE',url:'/users/1'})") 没有测试,但这样的东西应该工作. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |