Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inconsistency between running application callback execution and test results #22

Open
aprescott opened this issue Apr 7, 2014 · 1 comment

Comments

@aprescott
Copy link

Consider an Event model created by the following migration:

class AddEvents < ActiveRecord::Migration
  def change
    create_table :events do |t|
      t.string :event_classification
      t.integer :status
    end
  end
end

Any Event of a given event_classification is intended to have one and only one entry with status = 1, and all other Events should have status = 2 to represent that they are old.

This is achieved with an after_commit callback:

class Event < ActiveRecord::Base
  after_commit :invalidate_existing_events, on: [:update, :create]

  private

  def invalidate_existing_events
    Event.where(event_classification: "foo", status: 1).where.not(id: self.id).each do |event|
      event.status = 2
      event.save!
    end
  end
end

To verify the behaviour, open up a Rails console and run the following:

Event.create(event_classification: "foo", status: 1)
Event.create(event_classification: "foo", status: 1)

The outcome is that there are two Events:

[3] pry(main)> Event.find(1)
  Event Load (0.3ms)  SELECT `events`.* FROM `events` WHERE `events`.`id` = 1 LIMIT 1
=> #<Event id: 1, event_classification: "foo", status: 2>
[4] pry(main)> Event.find(2)
  Event Load (0.3ms)  SELECT `events`.* FROM `events` WHERE `events`.`id` = 2 LIMIT 1
=> #<Event id: 2, event_classification: "foo", status: 2>

This makes sense since

  1. id=2 saves and
  2. updates id=1 to set status=2, which then
  3. fires its own callback and
  4. updates id=2 to also have status=2.

However, the following test case passes:

require "spec_helper"

describe Event do
  specify do
    Event.create(event_classification: "foo", status: 1)
    Event.create(event_classification: "foo", status: 1)

    expect(Event.where(event_classification: "foo", status: 2).count).to eq(1)
    expect(Event.where(event_classification: "foo", status: 1).count).to eq(1)
  end
end

test_after_commit is in use, and spec_helper.rb sets config.use_transactional_fixtures = true.

That is: the spec does not arrive at the same result as the development console. This caused an issue with an application since the above test passes when it should fail.

I think this is a bug with test_after_commit since it claims to enable callbacks for testing but there is this discrepancy.

Version info:

  • Rails 4.0.4.
  • test_after_commit 0.2.3.
  • rspec and rspec-rails 2.14.1 (but also reproduced on later 0.0.x versions too).
@grosser
Copy link
Owner

grosser commented Aug 20, 2014

any patch or pending test-case welcome

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants