Ruby on rails 使用RSpec和mocking在提交后进行测试
我有一个模型潜在客户和一个回调:Ruby on rails 使用RSpec和mocking在提交后进行测试,ruby-on-rails,ruby,rspec,mocking,Ruby On Rails,Ruby,Rspec,Mocking,我有一个模型潜在客户和一个回调:在提交之后:创建,:发送给\u SPL 我使用的是Rails-4.1.0、ruby-2.1.1、RSpec 1) 此规范未通过: context 'callbacks' do it 'shall call \'send_to_SPL\' after create' do expect(lead).to receive(:send_to_SPL) lead = Lead.create(init_hash) p lead.new_recor
在提交之后:创建,:发送给\u SPL
我使用的是Rails-4.1.0、ruby-2.1.1、RSpec
1) 此规范未通过:
context 'callbacks' do
it 'shall call \'send_to_SPL\' after create' do
expect(lead).to receive(:send_to_SPL)
lead = Lead.create(init_hash)
p lead.new_record? # => false
end
end
2) 该规范也未通过:
context 'callbacks' do
it 'shall call \'send_to_SPL\' after create' do
expect(ActiveSupport::Callbacks::Callback).to receive(:build)
lead = Lead.create(init_hash)
end
end
3) 这一个正在通过,但我认为它不是在您提交回调后进行测试:
context 'callbacks' do
it 'shall call \'send_to_SPL\' after create' do
expect(lead).to receive(:send_to_SPL)
lead.send(:send_to_SPL)
end
end
在Rails中提交回调后测试的最佳方法是什么?尝试使用gem
或者在spec/support/helpers/test\u after\u commit.rb-中添加以下代码,我认为这应该是一个答案:
您还可以使用subject.run\u回调(:commit)
还要注意的是,这个问题(提交回调在事务测试中没有被调用)应该在rails 5.0+中得到修复,因此您可能希望在升级期间删除任何可能使用的解决方法。请参阅:我正在使用的配置可以轻松地在事务和截断之间切换,由于速度原因,前者是首选,但后者可以用于测试回调
RSpecbefore
和after
处理程序处理作用域,因此如果要将截断设置为作用域,请在处理程序之前定义一个
config.before(:each, truncate: true) do
DatabaseCleaner.strategy = :truncation
end
现在,要将此配置用于descripe
、context
或it
块,您应该声明如下:
describe "callbacks", truncate: true do
# all specs within this block will be using the truncation strategy
describe "#save" do
it "should trigger my callback" do
expect(lead).to receive(:send_to_SPL)
lead = Lead.create(init_hash)
end
end
end
完整的挂钩配置:(存储在spec/support/database\u cleaner.rb
)
更新Rails5
回调处理确实已经修复,但您可能仍然需要大量使用#reload
例如:
给定一个定义如下所示的创建后回调的模型:
after_create_commit { assign_some_association }
您可以通过以下方式指定此行为:
describe "callbacks" do
describe "assigning_some_association" do
subject(:saving) { record.save!; record.reload } # reload here is important
let(:record) { build(:record) }
it "assigns some association after commit" do
expect{ saving }.to(
change{ record.some_association_id }.from(nil).to(anything)
)
end
end
end
我用这样的东西
describe 'some method on record' do
let(:record) { create(:some_record) }
let(:update_block) { ->(record) { record.save! } } # define an labmda that will be called in a transaction block
let(:result_method) { :some_method } # define a method to be called
let(:result) do
record.class_eval <<~EVAL, __FILE__, __LINE__ + 1
after_commit :_record_result
def _record_result
@_result = public_send(:#{result_method})
end
EVAL
record.transaction do
update_block.call(record)
end
record.instance_variable_get(:'@_result')
end
before do
# apply changes to record
end
it 'returns the correct result' do
expect(result).to eq(some_value)
end
end
描述“记录中的某些方法”吗
let(:record){create(:some_record)}
让(:update_block){->(record){record.save!}}}}定义一个将在事务块中调用的labmda
让(:result_method){:some_method}#定义一个要调用的方法
让(:结果)去做
record.class\u eval您还可以使用subject.run\u回调(:commit)
在块体的末尾it
这个gem对Rails 3和Rails 4非常有效。在Rails 5中,它不再是必需的,因为它已添加到核心:如果使用on::update
定义回调,则我不处理4.2.7
。在运行回调之前,我还必须执行subject.instance\u variable\u get(:@\u start\u transaction\u state)[:new\u record]=false
,以使其工作,尽管它执行回调,但self.previous\u更改为{},这不是真的。怎么弄到的?
describe 'some method on record' do
let(:record) { create(:some_record) }
let(:update_block) { ->(record) { record.save! } } # define an labmda that will be called in a transaction block
let(:result_method) { :some_method } # define a method to be called
let(:result) do
record.class_eval <<~EVAL, __FILE__, __LINE__ + 1
after_commit :_record_result
def _record_result
@_result = public_send(:#{result_method})
end
EVAL
record.transaction do
update_block.call(record)
end
record.instance_variable_get(:'@_result')
end
before do
# apply changes to record
end
it 'returns the correct result' do
expect(result).to eq(some_value)
end
end