Dennis Kuczynski
2012-Jun-28 19:11 UTC
[rspec-users] Issue when testing ActiveRecord after_commit callbacks
In an ActiveRecord model, I have an after_commit callback (:enqueue_job) which places a job on my background processing queue (Sidekiq) To test that the callback was firing when the database transaction was committed, I was using: object.should_receive(:enqueue_job) #should pass Which seems to work. However, to test that the test was valid, I attempted object.should_not_receive(:enqueue_job) #should fail But this did not fail. I tracked this down to ActiveRecord''s DatabaseStatements'' commit_transaction_records method, which ends up eating the RSpec Negative Method Expectation Exception (which fails fast) https://github.com/rails/rails/blob/3-2-stable/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb If the negative method expectation did not fail fast, the test would probably work, but is there a better pattern for testing after_commit logic? (This was with rspec-mocks 2.10.1. use_transactional_fixtures was turned off to enable the callback.) Thanks, Dennis -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20120628/0d88f7fc/attachment.html>
David Chelimsky
2012-Jun-29 01:48 UTC
[rspec-users] Issue when testing ActiveRecord after_commit callbacks
On Thu, Jun 28, 2012 at 2:11 PM, Dennis Kuczynski <dennis.kuczynski at gmail.com> wrote:> In an ActiveRecord model, I have an after_commit callback (:enqueue_job) > which places a job on my background processing queue (Sidekiq) > > To test that the callback was firing when the database transaction > was?committed, I was using: > > object.should_receive(:enqueue_job) #should pass > > Which seems to work. ?However, to test that the test was valid, I attempted > > object.should_not_receive(:enqueue_job) #should fail > > But this did not fail. > > I tracked this down to ActiveRecord''s > DatabaseStatements''?commit_transaction_records method, which ends up eating > the RSpec Negative Method Expectation Exception (which fails fast) > https://github.com/rails/rails/blob/3-2-stable/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb > > If the negative method expectation did not fail fast, the test would > probably work, but is there a better pattern for testing after_commit logic? > > (This was with rspec-mocks 2.10.1. ?use_transactional_fixtures was turned > off to enable the callback.) > > Thanks, > DennisNice work finding the source of the problem. I guess you could do something like this: received = false obj.stub(:enqueue_job) do |*| received = true end # ... received.should be_true It ain''t pretty, but it should work (should fail properly if you say `received.should be_false`). HTH, David
Dennis Kuczynski
2012-Jun-29 16:32 UTC
[rspec-users] Issue when testing ActiveRecord after_commit callbacks
Thanks, that works. After thinking about what I was testing, I decided that I should really have just been checking that the background job ends up in the queue in the first place. So for my new tests, I''m ignoring all the messages within the after_commit, and just checking that the job is in the queue after the commit completes. -Dennis On Thursday, June 28, 2012 9:48:47 PM UTC-4, dchel... at gmail.com wrote:> > On Thu, Jun 28, 2012 at 2:11 PM, Dennis Kuczynski > <dennis.kuczynski at gmail.com> wrote: > > In an ActiveRecord model, I have an after_commit callback (:enqueue_job) > > which places a job on my background processing queue (Sidekiq) > > > > To test that the callback was firing when the database transaction > > was committed, I was using: > > > > object.should_receive(:enqueue_job) #should pass > > > > Which seems to work. However, to test that the test was valid, I > attempted > > > > object.should_not_receive(:enqueue_job) #should fail > > > > But this did not fail. > > > > I tracked this down to ActiveRecord''s > > DatabaseStatements'' commit_transaction_records method, which ends up > eating > > the RSpec Negative Method Expectation Exception (which fails fast) > > > https://github.com/rails/rails/blob/3-2-stable/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb > > > > If the negative method expectation did not fail fast, the test would > > probably work, but is there a better pattern for testing after_commit > logic? > > > > (This was with rspec-mocks 2.10.1. use_transactional_fixtures was > turned > > off to enable the callback.) > > > > Thanks, > > Dennis > > Nice work finding the source of the problem. I guess you could do > something like this: > > received = false > obj.stub(:enqueue_job) do |*| > received = true > end > # ... > received.should be_true > > It ain''t pretty, but it should work (should fail properly if you say > `received.should be_false`). > > HTH, > David > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20120629/d74be2db/attachment.html>