Ruby on Rails 2.3.8:在过滤之前忽略了破坏行为

所以,我正在乱用我的应用程序测试用户权限,但这个测试真的很奇怪。 这是我想要在我的ContentsController中工作的前filter:

before_filter :only => :destroy do |controller| controller.prevent_packet_sniffing_destroy_hack(controller_name.classify.constantize) end 

我正在努力让这个控制器的一组测试工作,以便我可以将之前的filter复制到具有类似行为的其他控制器

考试:

  should "not allow the deleting of #{plural_name} on different accounts" do login_as(@user) p = Factory(factory_name, :account => Factory(:account)) assert_difference("#{klass}.count", 0) do delete :destroy, :id => p.id klass.find_by_id(p.id).should_not be_nil end end 

对于那些感兴趣的人来说,这是一个广义的测试,我在所有具有类似function的对象上运行。 以下是方法参数’klass’定义的变量

  factory_name = klass.name.tableize.singularize.to_sym plural_name = klass.name.tableize singular_name = klass.name.tableize.singularize 

我试图测试的控制器的destroy方法:

  def destroy @content = Content.find(params[:id]) if not has_permission_to_change?(@content) flash[:error] = 'You do not have permission to delete this content.' else @content.destroy end respond_to do |format| format.html { redirect_to(contents_url) } end end 

执行权限测试的两种方法:

  def prevent_packet_sniffing_destroy_hack(klass) if not has_permission_to_change?(klass.find(params[:id])) puts "should be denying access" # render :template => "/error/401.html.erb", :status => 401 return false end end def has_permission_to_change?(object) if (current_user.is_standard? and object.user_id != current_user.id) or object.account_id != current_account.id return false else return true end end 

最后,控制台输出

 Loaded suite test/functional/contents_controller_test Started ...should be denying access E........ Finished in 1.068664 seconds. 1) Error: test: destroy contents! should not allow the deleting of contents on different accounts. (ContentsControllerTest): RuntimeError: This content should not be allowed to be deleted 

您会注意到,在测试过程中,失败的那个打印“应该拒绝访问”,就像我之前的filter中的puts一样。

我还在flash错误的正上方放置了一个puts语句,其中显示“您没有权限删除此内容”并且会打印出来。

*注意:当使用Web浏览器和数据包拦截器进行实际测试时,该function在开发模式下正常工作。

任何帮助深表感谢。

只需重新阅读您的测试:

 begin delete :destroy, :id => p.id raise "This #{singular_name} should not be allowed to be deleted" rescue ActiveRecord::RecordNotFound assert true end 

你在检查的是destroy行动是否顺利。 而且情况总是这样(除非没有你传递的Content ,但它怎么会发生?)。

实际上,您不会测试对象是否被销毁。

你应该这样重写它:

 should "not allow the deleting of #{plural_name} on different accounts" do login_as(@user) p = Factory(factory_name, :account => Factory(:account)) delete :destroy, :id => p.id klass.name.find_by_id(p.id).should be_nil end 

请注意,您在这里缺少unit testing,您应该使用存根来更多地隔离您的用例。