Last active
January 28, 2016 20:36
-
-
Save a-leung/64f8942367b6c3566500 to your computer and use it in GitHub Desktop.
rspec and ActiveRecord::Base.transaction testing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def set_new_name_on_items? | |
success = ActiveRecord::Base.transaction do | |
model.items.each do |i| | |
i.name = 'new name' | |
i.save or raise ActiveRecord::Rollback | |
end | |
!!success | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
it 'returns false on a single failing transaction' do | |
items = [ item_a, item_b ] | |
model = Fabricate(:model, items: items) | |
item_b.stub(:save!).and_return(false) | |
expect(model.set_new_name_on_items).to be false | |
end | |
it 'returns true on all save transaction' do | |
items = [ item_a, item_b ] | |
model = Fabricate(:model, items: items) | |
expect(model.set_new_name_on_items).to be true | |
end |
found a way to make the test work with and_return(false)
.
The important thing is to have raise ActiveRecord::Rollback
within the ActiveRecord::Base.transaction
so the every object in the transaction block is rolled back if any one of them errors. The previous example using save!
worked, but if one transaction in the block saved successfully, it would not rollback if another failed.
actually, best way to stub this is: .stub(:create_or_update)
:
From the docs:
# File activerecord/lib/active_record/base.rb, line 2575
def save
create_or_update
end
# File activerecord/lib/active_record/base.rb, line 2592
def save!
create_or_update || raise(RecordNotSaved)
end
so, save
and save!
are slightly different but both call create_or_update
.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
the spec was not passing since I stubbed item_b with:
and_return(false)
. To get the transaction block to fail, the stub must be:and_raise(Error)