[rspec-users] Issue when testing ActiveRecord after_commit callbacks

David Chelimsky dchelimsky at gmail.com
Fri Jun 29 01:48:47 UTC 2012


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


More information about the rspec-users mailing list