2010-07-02 16 views
0

J'ai eu du mal à comprendre pourquoi je peux facilement utiliser seeds.rb pour créer de nouveaux utilisateurs et leurs associations par défaut, mais lors de l'exécution individuelle d'une unité test provoque des erreurs. J'ai essayé de contourner l'appel 'Rôle' car il provoque des erreurs dans le test unitaire. Je suis relativement nouveau dans les tests unitaires, mais j'utilise Rails depuis plusieurs années déjà. Bien que tout fonctionne, je veux que les tests sortent sans erreur.Rails: Impossible d'initialiser has_many: par association à partir du test unitaire en utilisant le nom de la classe modèle

ruby 1.8.7
gem 1.3.7
Rails 2.3.8

app/modèles/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 => "[email protected]", :password => "abcde") 

test/unit/user_test.rb

test rubis
# assertions DO NOT fail, but raise the error below! 
def test_should_create_user_and_add_default_role 
    user = User.create(:name => '[email protected]', :password => 'abcde') #minimum length password 
    assert !user.new_record? 
    assert user.roles.exists?("subscriber") 
end 

/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'

Des pensées? Je n'arrive pas à trouver les meilleures pratiques qui interdisent cela ...

Répondre

0

À quoi ressemble Role.default? Il semble que cela retourne zéro dans l'environnement de test, donc je suppose que vous manquez l'enregistrement de rôle "par défaut" dans la base de données de test.

Par défaut, chaque test est exécuté dans une transaction, puis annulé une fois terminé. Vous devez donc configurer explicitement l'état de DB requis par vos tests. Vous pouvez utiliser peut-être utiliser des appareils ou le créer dans un bloc d'installation.

+0

J'ai modifié ci-dessus pour remplacer Role.default avec Role.find_by_name ("abonné"), car il était source de confusion dans l'autre sens. Si j'essaie roles.build (: name => "abonné"), le rôle est déjà pris, car les rôles sont créés par seeds.rb car ils sont partagés par les utilisateurs via UserRoles. J'ai également inclus la partie de seeds.rb qui charge le rôle par défaut dans le db. J'aurais aussi dû noter que j'ai développé la tâche db: rake de test dans lib/tasks/test_with_seeds.task, de sorte que seeds.rb est utilisé pour remplir la table Roles dans la base de données. Puis-je ne pas référencer un autre modèle directement dans un modèle? – domino

0

je devais éviter les montages par défaut de chargement et de détruire mes données de test, qui se charge de db/seeds.rb en éditant test/test_helper.rb

Néanmoins, il ne montre pas clairement les erreurs que mon test les données ont été munged, mais une fois que je l'ai écrit les essais qui a vérifié mes rôles par défaut sont (pas) en 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 => '[email protected]', :password => 'abcde') 
    assert user.roles.exists?(:name => "subscriber") 
end