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