Rails - validate inclusion fails on rake test:integration

I see different results when running 'rake test' and when running 'rake
test:integration'.

When running all tests with 'rake test' all tests pass.
When running 'rake test:integration' I have a failed test because my
model fails to validate inclusion of an attribute before saving.

My model looks something like:

  class Order < ActiveRecord::Base
    belongs_to :payment_type
    validates :payment_type, :inclusion => PaymentType.all
    ...
  end

PaymentType is a lookup table, which I have a fixture for.

When debugging the save method in the Order model I see that it fails
the inclusion validation (again, only when running just the integration
tests), but

  PaymentType.all.include?(payment_type)

evaluates to 'true'.

Any ideas why it fails when running only integration tests?

I see different results when running 'rake test' and when running 'rake
test:integration'.

When running all tests with 'rake test' all tests pass.
When running 'rake test:integration' I have a failed test because my
model fails to validate inclusion of an attribute before saving.

My model looks something like:

class Order < ActiveRecord::Base
   belongs_to :payment_type
   validates :payment_type, :inclusion => PaymentType.all
   ...
end

PaymentType is a lookup table, which I have a fixture for.

When debugging the save method in the Order model I see that it fails
the inclusion validation (again, only when running just the integration
tests), but

PaymentType.all.include?(payment_type)

evaluates to 'true'.

Any ideas why it fails when running only integration tests?

The call to validates (and thus the evaluation of its argument) happens when your order class is loaded. If this happens before your fixtures are loaded then you'll effectively be doing validates :blah, :inclusion => []

Why running rake test versus rake test:integration matters I don't know - perhaps one has extra dependencies that force fixtures to be loaded earlier or later, but either way I've generally tried to avoid this sort of thing. I'm not sure what your current code gets you over just validating the presence of the payment_type

Fred

Frederick Cheung wrote in post #1035416:

   belongs_to :payment_type

PaymentType.all.include?(payment_type)

evaluates to 'true'.

Any ideas why it fails when running only integration tests?

The call to validates (and thus the evaluation of its argument) happens
when your order class is loaded. If this happens before your fixtures
are loaded then you'll effectively be doing validates :blah, :inclusion
=> []

Why running rake test versus rake test:integration matters I don't know
- perhaps one has extra dependencies that force fixtures to be loaded
earlier or later, but either way I've generally tried to avoid this sort
of thing. I'm not sure what your current code gets you over just
validating the presence of the payment_type

Fred

Thanks Fred.
You're right, when debugging the validate inclusion code, I see that the
PaymentType.all returns [].

I guess, like you said, that when the Order class is loaded and the
inclusion is evaluated the PaymentType fixture wasn't loaded yet.

But that brings up another question, isn't that a bug in rake/rails?

Why aren't the fixtures being loaded prior to being used? Why isn't
PaymentType loaded before Order is?

Ori

I don't think any specific guarantees are made about when fixtures are
loaded apart from the fact that by the time your test runs they are
loaded or about the order in which any of this stuff happens.

Fred

Frederick Cheung wrote in post #1035592:

PaymentType loaded before Order is?

I don't think any specific guarantees are made about when fixtures are
loaded apart from the fact that by the time your test runs they are
loaded or about the order in which any of this stuff happens.

Fred

I understand that fixtures are guaranteed to be fully loaded only when
my test runs, the problem is, like you said, that the model class
validation is evaluated before that.

Another approach I tried was not to use fixtures at all, since payment
types are actually seed data and not sample data.
That approach failed as well for the same reason that the model
validation is called from the engine initialization which is done before
the seed data gets populated.

The question remains, how can I use validates inclusion on a lookup
table and not fail the test (when running only integration tests).

Ori

why validate the inclusion at all ? I'd validate the presence of the
foo_id column and use a foreign key constraint to ensure that it can't
contain junk.

Fred

Frederick Cheung wrote in post #1035726: