Ruby on Rails 2.3.8: Freaking destroy behavior ignores before filter
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.
精彩评论