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.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s