If you have a model that uses set_table_name you may hit a snag when trying to use fixtures and unit tests. The solution is twofold: name the fixture file using the legacy table name, and use the set_fixture_class method in your unit test. I coudn’t find this method mentioned in Agile Web Development with Rails, and there’s only a brief mention on the rubyonrails.com site. Still, some web searches turned up the answers.
Here is a simple example:
We’ll start with a table named libris_book
that contains book entries. The name libris_book won’t really fly with the Rails pluralized table name approach. It’s easy, however, to fix that disconnect in the model:
class Book < ActiveRecord::Base
set_table_name 'libris_book'
end
Let’s take a look at our data:
~/src/libris$ script/console
Loading development environment.
>> Book.count
=> 1230
Good enough. Now, we’ll be good little coders and write some unit tests using fixtures. We’ll create a fixture file and our test class:
books.yml
test_book:
title: Life in Lawrenceburg
author: Darren Day
book_test.rb
require File.dirname(__FILE__) + '/../test_helper'
class BookTest < Test::Unit::TestCase
fixtures :books
def test_fixtures
assert_equal(2,Book.count)
test_book = books(:test_book)
end
end
Looks good, but it won’t work!
~/src/libris$ rake test
(in /home/darrend/src/libris)
/usr/local/bin/ruby -Ilib:test "/usr/local/lib/ruby/gems/1.8/gems/rake-0.7.2/lib/rake/rake_test_loader.rb" "test/unit/book_test.rb"
Loaded suite /usr/local/lib/ruby/gems/1.8/gems/rake-0.7.2/lib/rake/rake_test_loader
Started
E
Finished in 0.01133 seconds.
1) Error:
test_fixtures(BookTest):
ActiveRecord::StatementInvalid: Mysql::Error: Table 'libris_test.books' doesn't exist: DELETE FROM books
...
Ugh. That doesn’t look pretty. After some googling around the following comes together
- Rename books.yml to libris_book.yml. The fixture yaml file has to share the same name as the database table name.
- Change the fixtures declaration to
fixtures :libris_book
. - Use set_fixture_class to connect the fixture to the model class.
Here is our new and improved book_test.rb file:
require File.dirname(__FILE__) + '/../test_helper'
class BookTest < Test::Unit::TestCase
set_fixture_class :libris_book => Book
fixtures :libris_book
def test_fixtures
assert_equal(2,Book.count)
test_book = libris_book(:test_book)
end
end