使用Mocha集成测试:Stub Ruby中ApplicationHelper的has_permission?方法
Stubbing
has_permission? Helper Method in Rails Integration Tests 我懂你现在的场景:你在app/helpers/application_helper.rb里定义了has_permission?权限检查方法,写集成测试的时候,发送GET请求到控制器得先过这个权限关卡,但你只想测试请求能不能到达目标方法,不想纠结权限逻辑,所以想Stub这个方法让测试顺利通过。你试了Object.any_instance的写法,这里给你几个更精准、更安全的实现方式:
1. 针对目标控制器精准Stub
因为你的控制器会自动包含ApplicationHelper,所以直接Stub目标控制器的实例方法就好,比全局StubObject靠谱多了,不会影响其他测试:
require 'test_helper' class YourTargetControllerIntegrationTest < ActionDispatch::IntegrationTest test "request reaches the target action when permission is stubbed" do # 替换目标控制器实例的has_permission?方法,返回true让权限检查通过 YourTargetController.any_instance.stubs(:has_permission?).returns(true) # 发送GET请求到你要测试的路由 get your_target_route_path # 断言请求成功到达目标方法,比如检查响应状态码或页面元素 assert_response :success assert_select "div.target-content", text: "Expected Content" end end
2. 全局统一Stub(适合多控制器测试)
如果你的权限检查是全局通用的,多个控制器测试都需要绕过这个方法,可以在测试基类的setup里统一配置:
class ActionDispatch::IntegrationTest setup do # 所有继承自ApplicationController的控制器都会被Stub这个方法 ApplicationController.any_instance.stubs(:has_permission?).returns(true) end end
这样每个集成测试运行前都会自动Stub,不用重复写代码。
3. 避免用Object.any_instance的原因
你之前尝试的Object.any_instance.expects(:has_permission?).returns(true)虽然能生效,但它会影响所有对象的has_permission?方法,很容易导致其他测试出现莫名其妙的问题——比如某个无关的类刚好也有这个方法,就会被意外Stub。所以尽量针对具体的控制器类来Stub,范围越小越安全。
4. Minitest用户的块级Stub写法
如果你用的是Rails默认的Minitest而不是RSpec,推荐用块级Stub,这样Stub只在块内生效,块结束后方法会恢复原样:
test "request reaches target action with Minitest stub" do YourTargetController.any_instance.stub(:has_permission?, true) do get your_target_route_path assert_response :success end end
内容的提问来源于stack exchange,提问作者raycons
相关产品推荐
相关产品推荐

