Home Play Pinja Bobbity flop

A blog about Ruby, Rails and other Tech. Mostly.

Back to blog

9th Oct 2007, 9:37am
Rails testing - two gotchas

Gotcha 1

Failing tests. We'd like them to pass of course. But there is something strange going on - the error is not a test error, it seems to come from rails itself:

  1) Error:
test_searcher_email(OrderMailerTest):
NoMethodError: You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.[]
    /usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.4/lib/active_record/fixtures.rb:498:in `orders'
    ./test/unit/order_mailer_test.rb:22:in `test_searcher_email'

1 tests, 0 assertions, 0 failures, 1 errors

What does it mean? The clue here is that the error comes from fixtures.rb. The other thing to note is that I have a setup in my test:

  def setup
    ActionMailer::Base.delivery_method = :test
    ActionMailer::Base.perform_deliveries = true
    ActionMailer::Base.deliveries = []
   ...
  end
Which should be fine, but there is this nasty error. Let's try something in the setup method - we'll add a call to super there:
  def setup
    ActionMailer::Base.delivery_method = :test
    ActionMailer::Base.perform_deliveries = true
    ActionMailer::Base.deliveries = []
    ...
    super
  end
And the result:
Started
.
Finished in 0.160284 seconds.

1 tests, 1 assertions, 0 failures, 0 errors
Great, that's fixed it. But why? Well it took me a while to find it. Have a look in /usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.4/lib/active_record/fixtures.rb - there is your culprit at line 554:
     alias_method :setup, :setup_with_fixtures
So the rule is, if you override setup you need to call super otherwise you don't get your fixtures set up properly.

Gotcha 2

Ever tried to test your routes? You should. But if you have routes that depend on what's in your database you've got a problem. Why? Because the routing is initialised before any fixtures are loaded. In fact none of the test related code is loaded at that point. So your tests just won't work.

I don't know a good way to fix this. In the end I opted for a fudge at the beginning of routes.rb:

  if ENV['RAILS_ENV'] == "test" && Category.count == 0
    Category.create!(:name=>"Families and Friends", :alternative_name=>"Family")
  end
And I have a fixture that contains the same information. This isn't really DRY, but I don't really see a good way to do this. Maybe we could read the fixtures file ourselves and get the data from there.

But at least the tests run ok now.


Back to blog