为了在控制器中跳过 Pundit 授权,您需要存根
从 Policy 类的new 方法中返回一个占位符/模拟对象
以true 响应正在测试的操作中的操作策略;
例如for FooController my FooPolicy 返回一个新的自身实例
在index 中调用其操作策略index? 时返回true
控制器动作。
对于 Minitest,它看起来像这样
# - Minitest -
foo_policy = MiniTest::Mock.new
foo_policy.expect :index?, true
FooPolicy.stub :new, foo_policy do
# your controller action test
end
您将创建一个模拟对象,该对象将扮演 Policy 的新实例的角色
控制器操作中的对象,并返回该模拟对象,如果策略的
new 方法在测试期间在其块范围内被调用。
如果您使用 Mocha,我相信以下方法也可以实现相同的效果
如上所述,但无需在其块中指定测试资产。
# - Mocha -
foo_policy = mock("foo_policy")
foo_policy.expects(:index?).returns(true)
FooPolicy.any_instance.stubs(:new).returns(foo_policy)
另外,您可以使用mock = Object.new 和存根实现类似的模拟对象
通过为mock 内联定义一个方法,如def mock.index?。这
也适用于现有的类,因为 Ruby 允许您重新声明一个方法
对于像 def FooPolicy.new 这样的类内联,并且只在
测试范围。知道了这一点,我们可以拥有def FooPolicy.new 并返回
我们的mock 如下所示
# - Without a Test-framework -
foo_policy = Object.new # create a mock / double
def foo_policy.index?; true; end # stub a method
def FooPolicy.new # stub Policyclass to return double with stubbed method
foo_policy = Object.new
def foo_policy.index?; true; end
foo_policy
end
为了完整起见,我使用 RSpec 并使用以下内容来删除我的 Pundit
我的控制器操作中的策略
# - Rspec -
foo_policy = instance_double("policy", index?: true)
allow(FooPolicy).to receive(:new).and_return(foo_policy)
至于 Devise,我使用以下支持测试助手,并且仅将它们包含在
需要用户在测试前sign_in 的控制器和请求测试:
module DeviseRequestSpecHelpers
include Warden::Test::Helpers
def sign_in(resource_or_scope, resource = nil)
resource ||= resource_or_scope
scope = Devise::Mapping.find_scope!(resource_or_scope)
login_as(resource, scope: scope)
end
def sign_out(resource_or_scope)
scope = Devise::Mapping.find_scope!(resource_or_scope)
logout(scope)
end
end
见Module: Warden::Test::Helpers — Documentation for hassox/warden (master)
有关Warden::Test::Helpers 模块的更多信息
这是因为 Warden 在 Devise 中使用了它的测试助手。
这个Warden::Test::Helpers 模块在包含时会将Warden 切换到它的
test_mode! 及其 login_as 方法会将您的 user 对象设置为
current_user 用于测试,在您的
申请。
参考资料: