我在试着删除一个关联。所涉及的两个模型是User和Cancellation。
class Cancellation < Active Record::Base
belongs_to :taker, class_name: "User"
end
class User < ActiveRecord::Base
has_many :taken_cancellations, class_name: "Cancellation", foreign_key: :taker_id
end在我的测试中,我得到了以下代码:
describe "Admin Calendar" do
subject { page }
let!(:user) { FactoryGirl.create(:user, name: "Taker User") }
let(:cancellation) { FactoryGirl.create(:cancellation, start_at: 2.days.from_now, taker: user) }
before do
sign_in admin
visit edit_admin_cancellation_path cancellation
end
#...
describe "Edit Page" do
it 'Making it available' do
expect { click_link "Make it available" }.to change(cancellation.reload, :taker).from(user).to nil
end
end
endclick_link 'Make it available将在控制器中触发user.taken_cancellations.delete @cancellation。
此错误导致测试失败:
taker should have been changed to nil, but is now #<User id: 1, name: "Taker User"...来自let方法指南:https://relishapp.com/rspec/rspec-core/v/2-6/docs/helper-methods/let-and-let
该值将被缓存在同一个示例中的多个调用中,而不是跨示例缓存。
在我看来,change方法似乎是在操作之后创建一个新的cancellation,而不是查看回忆录。我没想到会有这种行为。
测试在使用块时通过,如下所示:
expect { click_link "Make it available" }.to change { cancellation.reload.taker }.from(user).to nil有人能解释我说得对吗?为什么会有这些不同的行为?
发布于 2015-01-28 04:16:47
在第一种形式中,对cancellation.reload进行一次计算,结果对象在调用click_link方法之前和之后发送消息taker。换句话说,在调用cancellation之后,不会重新加载click_link对象。
在第二种形式中,在调用cancellation.reload.taker之前和之后对click_link进行完整的评估,因此reload有机会在数据库更新之后生效。
但是请注意,根据您的配置,处理click_link结果的服务器可能在一个单独的线程中执行,因此在任何情况下,数据库的更新和测试断言之间都存在竞争条件。
https://stackoverflow.com/questions/28155136
复制相似问题