开发者

Ruby on Rails 2.3.8: Freaking destroy behavior ignores before filter

开发者 https://www.devze.com 2023-03-20 14:34 出处:网络
So, I\'m messing around with testing user permission in me app, but this test is really weird. Here is the before filter I\'m trying to get to work in my ContentsController:

So, I'm messing around with testing user permission in me app, but this test is really weird. Here is the before filter I'm trying to get to work in my ContentsController:

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

I'm working on getting just this one controller's set of tests to work so that I can copy the before filter into the other controllers with similar behavior

The test:

 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

for those interested, this is a generalized test that I run over all objects with similar functionality. Here are the variable defined by the method parameter, 'klass'

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

the destroy method for the controller I'm trying to test:

 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

The two methods that do permissions testing:

  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

and finally, the console output

Loaded suite test/functional/contents_controller_test
Started
...should be denying access
E........
Finished in 1.068664 seconds.

  1) Error:
test: des开发者_如何学运维troy contents! should not allow the deleting of contents on different accounts. (ContentsControllerTest):
RuntimeError: This content should not be allowed to be deleted

You'll notice that in the middle of the tests, the one that fails prints "should be denying access" as in the puts in my before filter.

I've also put a puts statement right above the flash error where it says "you do not have permission to delete this content" and that gets printed.

*Note: the functionality correctly works in development mode, when actually tested with a web browser and packet interceptor.

Any help is much appreciated.


Just re-read your test:

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

What you're checking there is whether or not the destroy action goes well. And it's always the case (unless there is no Content with the id you pass but how could it ever happen?).

You actually don't test whether or not the object is destroyed or not.

You should rewrite it this way:

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

Note that you're lacking unit tests here and you should isolate your use cases a bit more using stubs.

0

精彩评论

暂无评论...
验证码 换一张
取 消