Ruby on rails 坎坎坎能力测试不';我不能通过,但它工作得很好

Ruby on rails 坎坎坎能力测试不';我不能通过,但它工作得很好,ruby-on-rails,rspec,cancancan,Ruby On Rails,Rspec,Cancancan,我的ability.rb中定义了以下能力: if user.role? :chief can [:action1, :action2], Request, user: {id: user.subordinate_ids} end 在我的能力测试中,我有以下几点: subject{ Ability.new(user) } let(:user) { create(:chief_user) } let(:subordinate) { create(:user, boss: user) } i

我的ability.rb中定义了以下能力:

if user.role? :chief
   can [:action1, :action2], Request, user: {id: user.subordinate_ids}
end
在我的能力测试中,我有以下几点:

subject{ Ability.new(user) }
let(:user) { create(:chief_user) }
let(:subordinate) { create(:user, boss: user) }

it { is_expected.to be_able_to([:action1, :action2], Request.new(user: subordinate)) }
在进行手动测试时,该功能按预期工作,但我无法使此测试正常工作。我尝试了使用适当的参数Request.create,但仍然得到相同的结果

我已经做了一些调试,相应的关联是有序的(主管有下属,请求属于下属,所以实际测试是主管只能执行操作1,操作2他的下属的请求)

我正在使用CanCanCan和RSpec进行测试


关于如何使这个测试工作的任何见解?

rspec's let语法基本上是使用Proc(延迟加载),因此在调用它之前,它实际上不会持久化。当您在规范中调用它时,有时您正在测试一些尚未持久化的东西

您可以通过添加before块来检查这一点

subject{ Ability.new(user) }
let(:user) { create(:chief_user) }
let(:subordinate) { create(:user, boss: user) }

it { is_expected.to be_able_to([:action1, :action2], Request.new(user: subordinate)) }
尝试添加下面的before行

subject{ Ability.new(user) }
let(:user) { create(:chief_user) }
let(:subordinate) { create(:user, boss: user) }

# new line to ensure object exists before test run
before {expect(subordinate).to eq subordinate}

it { is_expected.to be_able_to([:action1, :action2], Request.new(user: subordinate)) }

这有点让IMO感到沮丧,但我以前遇到过这样的问题

通过这样做解决了这个问题:

subject{ Ability.new(user) }
let!(:user) { create(:chief_user) }
let!(:subordinate) { create(:user, boss: user) }
[:action1, :action2].each do |action|
    it { is_expected.to be_able_to(action, Request.new(user: subordinate)}
end

由于您使用的是let语法,在调用对象测试之前,您可能需要确保对象被持久化。您好,Dave,谢谢您的回答。确保对象持久化是什么意思?我已经做了一些调试,将puts放入其中,所有内容都按它应该的方式打印