2011-06-12 2 views
19

Je me bats avec le test de la méthode de mise à jour dans Rails. J'utilise le standard intégré dans le cadre d'essais (test::unit) et Rails 3.0.8. J'ai créé une application minimale pour le tester maintenant, mais je n'arrive pas à le faire fonctionner. Voici ce que je fais:Comment tester la méthode de mise à jour dans Rails

Je crée une nouvelle application Rails vide:

rails new testapp 

Créer un modèle appelé Collection:

rails generate model collection name:string 

Run rake db: migrate:

rake db:migrate 

Créer un contrôleur appelé Collections avec une méthode de mise à jour:

rails generate controller collections update 

En collection_controller.rb j'ajouter cette méthode de mise à jour minimum:

def update 
    @collection = Collection.find(params[:id]) 
    @collection.update_attributes(params[:collection]) 
end 

Les appareils de test sont les valeurs par défaut (collections.yml):

one: 
    name: MyString 

two: 
    name: MyString 

Puis-je ajouter cela à la collection_controller_test. rb sous fonctionnelle:

test "should update collection" do 
    put :update, :id => collections(:one), :collection => {:name => 'MyString2'} 
    assert_equal "MyString2", collections(:one).name 
end 

Lorsque j'exécute le test:

rake test:functionals 

Il échoue avec ce message:

test_should_update_collection(CollectionsControllerTest) [/Users/atle/Documents/Rails/testapp/test/functional/collections_controller_test.rb:6]: 
<"MyString2"> expected but was 
<"MyString">. 

Voici la sortie de test.log:

[1m[36mSQL (0.2ms)[0m [1m SELECT name 
FROM sqlite_master 
WHERE type = 'table' AND NOT name = 'sqlite_sequence' 
[0m 
[1m[35mCollection Load (0.1ms)[0m SELECT "collections".* FROM "collections" WHERE "collections"."id" = 980190962 LIMIT 1 
Processing by CollectionsController#update as HTML 
Parameters: {"id"=>#<Collection id: 980190962, name: "MyString", created_at: "2011-06-12 13:14:13", updated_at: "2011-06-12 13:14:13">, "collection"=>{"name"=>"MyString2"}} 
[1m[36mCollection Load (0.2ms)[0m [1mSELECT "collections".* FROM "collections" WHERE "collections"."id" = 980190962 LIMIT 1[0m 
[1m[35mAREL (0.2ms)[0m UPDATE "collections" SET "name" = 'MyString2', "updated_at" = '2011-06-12 13:14:13.394135' WHERE "collections"."id" = 980190962 
Rendered collections/update.html.erb within layouts/application (1.5ms) 
Completed 200 OK in 9ms (Views: 4.5ms | ActiveRecord: 1.2ms) 

Dans le journal, je peux voir la déclaration UPDATE, mais je ne vois jamais une nouvelle instruction SELECT.

Quelqu'un pourrait-il me expliquer ce que je fais mal s'il vous plaît?

+2

+1 pour une question clairement posée.C'est agréable de voir un nouvel utilisateur poser une question explicite avec ce niveau de détail. Votre problème provient certainement de 'collections (: one)' dans votre assertion, qui lit simplement à partir de l'appareil à la place de la base de données. Cameron et Teddy ont tous deux ceci correct ci-dessous. (BTW: Regardez dans "factory_girl" et vider les appareils complètement dès que possible, ils sont pratiques pour commencer, mais un désordre horrible plus tard.) – jdl

+0

Donc les appareils et le db sont deux endroits distincts. J'ai supposé que les appareils sont lus dans la base de données au démarrage et que les collections (: one) lues à partir de la base de données. Merci pour le nettoyage des choses et je vais regarder dans cette factory_girl :) – Atle

Répondre

13

Vous rechargez les données de l'appareil au lieu de lire depuis le db. Essayez quelque chose comme

assert_equal "MyString2", Collection.find(collections(:one)).name 

Vous devrez peut-être spécifier l'ID dans l'appareil.

Avis de non-responsabilité: Je n'ai pas testé.

+1

Cela a fonctionné, maintenant mes tests fonctionne, merci! – Atle

+0

N'utilisez pas la base de données dans le test si vous n'en avez pas besoin. Vous ne voulez pas tester si la base de données fonctionne, non? – schmijos

17

Vous pouvez faire des affirmations sur la variable d'instance qui est créée au cours de la réponse HTTP:

test "should update collection" do 
    put :update, :id => collections(:one), :collection => {:name => 'MyString2'} 
    assert_equal "MyString2", assigns(:collection).name 
end 
+0

Votre suggestion a fonctionné aussi, mais j'ai accepté la réponse de Camerons, puisqu'il était premier;) Merci! – Atle

+0

Ceci est la meilleure réponse, car il n'utilise pas la base de données. – schmijos

+0

Ceci est la bonne réponse. Collection.find (collections (: un)) est moche. – hellion

2

Ma variante préférée de ceci:

test "should update collection" do 
    coll = collections(:one) 
    put :update, :id => coll, :collection => {:name => "MyString2"} 
    assert_equal "MyString2", coll.reload.name 
end 

L'astuce assigns(:collection) ne garantit pas réellement l'enregistrement a été sauvé. Cela peut ne pas être un problème, ou cela peut être une surprise.

+0

Utilisez 'assigns' si possible. Vous n'avez besoin d'aucune interaction de base de données pour ce que vous voulez tester. – schmijos

Questions connexes