Ruby on Rails 2.3.8:在过滤器之前忽略破坏行为会破坏行为 [英] Ruby on Rails 2.3.8: Freaking destroy behavior ignores before filter
问题描述
因此,我正在测试我的应用程序中的用户权限,但是这个测试确实很奇怪. 这是我试图在ContentsController中工作的before过滤器:
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
我正在努力使一个控制器的测试集能够正常工作,以便可以将before过滤器复制到其他具有类似行为的控制器中
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
测试:
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'定义的变量
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
我要测试的控制器的destroy方法:
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
最后是控制台输出
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
您会注意到,在测试的中间,如我的before过滤器中的puts所示,测试失败的结果应该拒绝访问".
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.
我还在Flash错误的上方放了一个puts语句,上面写着您无权删除此内容",然后将其打印出来.
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.
*注意:在使用Web浏览器和数据包拦截器进行实际测试时,该功能可以在开发模式下正常工作.
*Note: the functionality correctly works in development mode, when actually tested with a web browser and packet interceptor.
非常感谢您的帮助.
推荐答案
只需重新阅读测试:
begin
delete :destroy, :id => p.id
raise "This #{singular_name} should not be allowed to be deleted"
rescue ActiveRecord::RecordNotFound
assert true
end
您要检查的是destroy
操作是否正常.而且总是这样(除非您通过的id
中没有Content
,但它怎么会发生?).
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?).
您实际上不测试对象是否被破坏.
您应该这样重写它:
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.
这篇关于Ruby on Rails 2.3.8:在过滤器之前忽略破坏行为会破坏行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!