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

时间:2011-07-13 17:35:05

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

所以,我正在乱用我的应用程序测试用户权限,但这个测试真的很奇怪。 这是我试图在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

我试图测试的控制器的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

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

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

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

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

重新阅读你的测试:

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没有id,但它怎么会发生?)。

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

你应该这样重写:

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

请注意,您在此处缺少单元测试,您应该使用存根稍微隔离用例。