Jamie Macey
2006-Oct-05 20:39 UTC
[mocha-developer] ActiveRecord Validations - validates_uniqueness_of
David Chelimsky <dchelimsky at gmail.com> wrote:> What I would really want to ensure here is that Person validates > uniqueness of email, not how it does it. What I would do is something > like: > > def test_person_should_validate_uniqueness_of_email > assert_true Person.new(:email => "a at b.com").save > assert_false Person.new(:email => "a at b.com").save > end > > The primary argument against this approach is that this test requires > real interaction w/ the database and unit tests aren''t supposed to > interact w/ the database. While I usually agree w/ that perspective, I > think that needs to be balanced against the fact that AR is very > closely tied to the database. So my approach tends towards testing the > behaviour (not the implementation) of model classes in the "unit > tests" allowing database interaction, but mocking/stubbing that > behaviour in "functional" and/or "integration" tests. > > I''m curioius to hear other people''s perspective on this.Dave, I''ve been doing a few things like this recently trying to avoid as many database hits as I can. I still haven''t figured out a great way to do this for stock validations, but I am making a point of keeping the database clean, and verifying explicit things. My take on the above would be like so: def valid_person(opts={}) Person.new({:email => "a at b.com"}.merge(opts)) end def test_person_should_validate_uniqueness_of_email person = valid_person person.save assert_false valid_person.valid? assert_true valid_person(:email => "b at b.com").valid? person.destroy end Having the valid_foo shortcut helps immensely once you get behond a handful of validations. As for the test itself, I''m cleaning up the entry that does make it to the database, and preventing more potential database hits by just calling valid? instead of save. I suppose I could be a bit pedantic and create a new valid_person, call valid?, and then check that it has the correct error on the email field, but I think in this case it''s pretty much overkill. - Jamie