Monday, February 18, 2008

ActiveRecord Double Validation Errors in RSpec

I had a strange error occur in one of my rspec model unit tests today, and I wanted to document it here because my solution (which is a bit of a hack) is the opposite of what worked for other people.

I have a bunch of tests that check to make sure I'm validating various properties of a model. All of a sudden, I started having tests fail because the validations seemed to be adding the same error twice.
'User creation should require domain names to be unique' FAILED
expected 1 error on :domain, got 2
This error only occured when my full suite of tests ran. If I ran the unit test by itself (or even if I just ran only the model tests by themselves), it didn't happen.  Unfortunately I didn't notice whatever it was I did to introduce this error, so I couldn't reverse it.

Several other people have encountered this problem, so I know it's because my tests are leaking state in some way.  Somehow I am doing something during my tests that rspec isn't able to clean up.  Usually it's because the tests are doing something weird with extra require or load statements, which causes multiple copies of the class to be loaded.  Removing these statements usually works.  

I had no such statements and so spent a while trying to sort this out.  On a whim, I added a require statement to the top of the failing User model spec, and that fixed it:
require 'user'
I wish I had more time to investigate, because it makes me thing I don't know enough about Rails autoloading behavior, or Ruby's loading behavior. 

If you're running into this same problem, I found these mailing lists threads to be useful:

3 comments:

dkubb said...

I found something like this when I required the model twice due to slightly different paths. By default ruby keeps track of what you've required based on the path, and if the path differs at all, then it will require the same file two or more times. I've found that consistently using File.expand_path to normalize the path you're requiring helps alot. I wish ruby did this automatically.

Shad said...

Thanks Mike! This got me on the right path :)

Anonymous said...

"Do you think Oz could give me courage?" asked the Cowardly Lion.
"Just as easily as he could give me brains," said the Scarecrow.
"Or give me a heart," said the Tin Woodman.
"Or send me back to Kansas," said Dorothy.

Nike shoes
MBT
supra footwear
famous footwear
shoe dept
nike air max