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