Ruby on Rails 4.2.6下如何编写Study::BasePolicy的Spec测试?
嘿,我来帮你搞定这个Policy测试的问题!
修复Study::BasePolicy的RSpec测试报错
首先看你遇到的NameError,大概率是因为在测试里直接用Base.new,但你的Policy是命名空间下的Study::BasePolicy,Ruby找不到未限定命名的Base类。下面是正确的测试写法,我一步步给你拆解:
1. 正确的测试文件结构和基础设置
首先你的测试文件应该放在spec/policies/study/base_policy_spec.rb,这样RSpec能正确加载对应的Policy类。然后基础的测试框架应该是这样:
require 'rails_helper' RSpec.describe Study::BasePolicy, type: :policy do # 定义测试用的用户和记录(ApplicationPolicy默认需要record参数) let(:user) { create(:user) } # 假设你有User的factory,没有的话可以用User.new模拟 let(:record) { OpenStruct.new } # 如果没有对应模型,用OpenStruct模拟即可 let(:policy) { described_class.new(user, record) } # 测试default?方法 describe "#default?" do context "when user has edit access" do before { allow(user).to receive(:has_edit_access?).and_return(true) } it "grants access" do expect(policy.default?).to be true end end context "when user does NOT have edit access" do before { allow(user).to receive(:has_edit_access?).and_return(false) } it "denies access" do expect(policy.default?).to be false end end end # 测试terminology_toggle?方法 describe "#terminology_toggle?" do context "when user has edit access" do before { allow(user).to receive(:has_edit_access?).and_return(true) } it "grants access" do expect(policy.terminology_toggle?).to be true end end context "when user does NOT have edit access" do before { allow(user).to receive(:has_edit_access?).and_return(false) } it "denies access" do expect(policy.terminology_toggle?).to be false end end end end
2. 报错的核心原因
你之前的测试里写了let (:base) {Base.new},这里的Base没有指定命名空间Study::,Ruby会去顶级命名空间找Base类,自然找不到,所以抛出NameError。解决办法就是要么用Study::BasePolicy.new,要么用RSpec的described_class(更推荐,重构的时候不用改)。
3. 额外的注意事项
- 如果你有对应的
Study::Base模型,把OpenStruct.new替换成create(:study_base)或者对应的实例化代码即可。 - 确保你的
User模型确实有has_edit_access?方法,或者在测试里像上面那样用allow来mock这个方法的返回值。 - 要是你用了Pundit的测试辅助方法,也可以用更简洁的写法验证权限:
it "permits terminology_toggle action" do expect(policy).to permit_action(:terminology_toggle) end
内容的提问来源于stack exchange,提问作者Jakub
相关产品推荐
相关产品推荐

