开发者

Rails: Unable to initialize has_many :through association from within unit test using model class name

I've been struggling to understand why I can easily use seeds.rb to create new Users and their default associations, but when running individual a unit test causes errors. I've tried to get around calling 'Role' as it causes errors in the unit test. I am relatively new to unit testing, but have been using Rails for several years already. Although it all works, I want the tests to come out error free.

ruby 1.8.7

gem 1.3.7

Rails 2.3.8

app/models/user.rb

class User < ActiveRecord::Base

  has_many :user_roles, :dependent => :destroy              
  has_many :roles, :through => :user_roles, :uniq => true, :order => :id

  has_one  :contact, :as => :owner, :dependent => :destroy

  attr_accessor   :password

  before_save :build_default_associations, :if => :new_record?

def build_default_associations
  update_encrypted_password
  build_contact(:email => name) 
  user_roles.build(:role_id => Role.find_by_name("subscriber")id )
  #
  # the below also works in seeds.rb but causes a different error
  # roles << Role.find_by_name("subscriber") 
  # ActiveRecord::AssociationTypeMismatch: Role(#2162845660) expected, got NilClass(#2148404100)
  # 
end

db/seeds.rb

# This places the default Role in the db
Role.create({:name => "subscriber", :description => "This will be the default"})
# associations initialize and save with 
User.create(:name => "valid@email.com", :password => "abcde")  

test/unit/user_test.rb

# assertions DO NOT fail, but raise the error below! 
def test_should_create_user_and_add_default_role
  user = User.create(:name => 'ok@good.org', :password => 'abcde') #minimum length password
  assert !user.new_record?
  assert user.roles.exists?("subsc开发者_如何学运维riber")
end

ruby test/unit/user_test.rb

1) Error:

test_should_create_user_and_add_default_role(UserTest):

RuntimeError: Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id

app/models/user.rb:31:in 'build_default_associations'

unit/user_test.rb:31:in `test_should_create_user_and_add_default_role'

Any thoughts? I can't seem to find any best practices that prohibit this...


What does Role.default look like? It seems like it's returning nil in the test environment, so I'd assume you're missing the "default" Role record in the test DB.

By default each test is run within a transaction and then rolled back once it's finished, so you'll need to explicitly setup any DB state your tests require. You could use perhaps use fixtures or create it in a setup block.


I needed to prevent the default fixtures from loading and destroying my test data, which is loading from db/seeds.rb by editing test/test_helper.rb

Still it was not clear from the errors that my test data was munged, but once I wrote the tests that verified my default Roles were (not) in place....

test/unit/user_test.rb

def test_users_exist
  assert_equal User.count, 8   # test was expecting 2, b/c of default yml fixtures!
end

test/test_helper.rb

# Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
#
# Note: You'll currently still have to declare fixtures explicitly in integration tests
# -- they do not yet inherit this setting
# fixtures :all  <--- for now load none, since testing data from db/seeds.rb

test/unit/user_test.rb

# No error, No fail 
def test_should_create_user_and_find_default_role
  user = User.create(:name => 'ok@good.org', :password => 'abcde')
  assert user.roles.exists?(:name => "subscriber") 
end
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜