【问题标题】:Ruby on Rails 2.3.8: Freaking destroy behavior ignores before filterRuby on Rails 2.3.8:在过滤器之前忽略了可怕的破坏行为
【发布时间】:2011-07-13 17:35:04
【问题描述】:

所以,我在我的应用程序中测试用户权限,但这个测试真的很奇怪。 这是我试图在 ContentsController 中使用的前置过滤器:

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

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

测试:

 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

对于那些感兴趣的人,这是一个通用测试,我对所有具有相似功能的对象进行了测试。 这里是方法参数定义的变量,'klass'

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

我要测试的控制器的销毁方法:

 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

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

我还在 flash 错误上方放置了一个 puts 语句,上面写着“您无权删除此内容”并被打印出来。

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

非常感谢任何帮助。

【问题讨论】:

  • has_permission_to_change 的值是多少? ?
  • 它返回 false(通过 puts 检查)

标签: ruby-on-rails ruby functional-testing


【解决方案1】:

重新阅读你的测试:

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

您在那里检查的是destroy 操作是否顺利。情况总是如此(除非没有 Contentid 你通过了,但它怎么可能发生呢?)。

你实际上并没有测试对象是否被销毁。

你应该这样重写它:

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

请注意,您在这里缺少单元测试,您应该使用存根更多地隔离您的用例。

【讨论】:

  • 好吧,测试不应该让对象被删除,因为我以@user 身份登录,并创建了一个@user 不可能分开的不同帐户。之前的过滤器应该可以解决这个问题。逻辑都很好……但是那里正在发生其他事情。我确实喜欢你关于测试的建议......我会编辑我的帖子以反映它。
  • 你误会了:having the destroy action running okhaving an object deleted 不同
  • 你是对的。我只是想,既然不允许被删除,它应该抛出RecordNotFound,然后忽略块的其余部分...... idk...... S
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多