[rspec-users] factory girl rspec and authlogic

Stephen Eley sfeley at gmail.com
Sun Oct 4 00:31:18 EDT 2009


On Sat, Oct 3, 2009 at 8:41 PM, Don French <dhf0820 at gmail.com> wrote:
> I am trying some simple test using the above items. Using the
> Factory.create(...) gives Active Record errors and not the failure of
> the test. Change it to u = Factory.build(...) then u.save, I do not
> get the Active record error but the proper test failure message.

I don't think you have a problem with Factory Girl *or* with RSpec.
Both are working as intended.  Factory Girl's 'create' method is
calling 'save!' instead of 'save' -- the difference being that 'save!'
throws an exception instead of returning false when validations fail.
That's exactly what you're seeing.  And it's reasonable, because if
you ask it to create a record, it assumes that you *want a record*,
and that an inability to make one is unexpected.  The 'build' method
is intended exactly for things like validation testing.

There are a few better ways you can test for this than what you're
doing.  One is to try 'create' and test for the exception it throws:

it 'requires email' do
  lambda { Factory.create(:valid_user, :email => nil) }.should
raise_error(ActiveRecord::RecordInvalid)
end

...This would work, but it's clunky.  I don't like lambdas if I can
avoid them.  I would probably do it like this instead:

it 'requires email' do
  u = Factory.build(:valid_user)
  u.email = nil
  u.should_not be_valid
end

Assuming another test where a :valid_user proved to actually *be*
valid, this is entire and sufficient.

If you consider it important to know what the error messages are well
(I generally don't), you could also do:

it 'requires email' do
  u = Factory.build(:valid_user)
  u.email = nil
  u.save.should be_false
  u.should have(2).errors.on("email")
  u.errors.on("email").should include("is too short (minimum is 6 characters)")
  u.errors.on("email").should include("should look like an email address.")
end

In practice, even if I did care about all of that, I'd split them out
into separate examples, because I subscribe to the philosophy that a
good example should have at most one expectation.  Four "shoulds" is
three too many.  But that's a subtle distinction, and I wanted to be
brief here.

The one thing I _wouldn't_ do is what you're doing in both code
blocks, which is to wrap an expectation inside a lambda and then put
_another_ expectation outside it.  Checking that the record count did
not change is really unnecessary.  The save failed.  That's
sufficient.

(By the way, if I screwed up any of the syntax with Factory Girl here,
my apologies.  I don't use it; I use Machinist.  That's another one of
those personal preference things, though.)


-- 
Have Fun,
   Steve Eley (sfeley at gmail.com)
   ESCAPE POD - The Science Fiction Podcast Magazine
   http://www.escapepod.org


More information about the rspec-users mailing list