2009-09-20 7 views
34

Pendant l'apprentissage de Rails, j'ai créé une application avec un contrôleur Domains imbriqué sous un contrôleur Customers. J'utilise Rails 2.3.4 et ça a été une expérience d'apprentissage. J'ai réussi à obtenir le routage ci-dessous mis en place:Rails: comment modifier les tests d'une ressource imbriquée?

customer_domains GET /customers/:customer_id/domains(.:format)   {:controller=>"domains", :action=>"index"} 
        POST /customers/:customer_id/domains(.:format)   {:controller=>"domains", :action=>"create"} 
new_customer_domain GET /customers/:customer_id/domains/new(.:format)  {:controller=>"domains", :action=>"new"} 
edit_customer_domain GET /customers/:customer_id/domains/:id/edit(.:format) {:controller=>"domains", :action=>"edit"} 
    customer_domain GET /customers/:customer_id/domains/:id(.:format)  {:controller=>"domains", :action=>"show"} 
        PUT /customers/:customer_id/domains/:id(.:format)  {:controller=>"domains", :action=>"update"} 
        DELETE /customers/:customer_id/domains/:id(.:format)  {:controller=>"domains", :action=>"destroy"} 
      customers GET /customers(.:format)        {:controller=>"customers", :action=>"index"} 
        POST /customers(.:format)        {:controller=>"customers", :action=>"create"} 
     new_customer GET /customers/new(.:format)       {:controller=>"customers", :action=>"new"} 
     edit_customer GET /customers/:id/edit(.:format)      {:controller=>"customers", :action=>"edit"} 
      customer GET /customers/:id(.:format)       {:controller=>"customers", :action=>"show"} 
        PUT /customers/:id(.:format)       {:controller=>"customers", :action=>"update"} 
        DELETE /customers/:id(.:format)       {:controller=>"customers", :action=>"destroy"} 
       root  /            {:controller=>"customers", :action=>"index"} 

Cependant, tous les tests pour le contrôleur Domaines échouent en raison d'erreurs de routage.

Par exemple, le test suivant (généré par le générateur de ressources de Rails) échoue, comme tous les autres tests de la classe DomainsControllerTest.

class DomainsControllerTest < ActionController::TestCase 
    test "should get index" do 
    get :index 
    assert_response :success 
    assert_not_nil assigns(:domains) 
    end 
end 

Il échoue avec l'erreur:

No route matches {:action => "index", :controller => "domains"} 

Cela est logique puisque les routes par défaut n'existent et le contrôleur de domaines exige une @customer à régler. J'ai passé un après-midi à chercher le changement nécessaire, mais presque tous les sites parlent des tests Rspec au lieu des tests Rails réguliers. Comment puis-je modifier le code domains_controller_test.rb pour qu'il comprenne la ressource imbriquée? Passer le customer_id avec les demandes ferait l'affaire

Répondre

47

. Quelque chose comme ceci: -

 
class DomainsControllerTest < ActionController::TestCase 
    test "should get index" do 
    get :index ,:customer_id=> 1 
    assert_response :success 
    assert_not_nil assigns(:domains) 
    end 
end 
+0

Cela semble fonctionner, Rishav. Y a-t-il un moyen de SECHER cela, au lieu de passer l'identifiant à chaque test séparé? –

+1

Martijn, c'est ce que tu vas devoir faire. Votre routage doit connaître le client pour travailler. Je suppose que vous pourriez écrire une aide de test pour remplacer l'appel "get" qui remplit automatiquement la partie customer_id du hachage, mais cela semble être une mauvaise idée sauf si vous écrivez beaucoup, beaucoup de tests contre le DomainsController. –

+1

Je veux juste vous dire pourquoi sécher ce peut être une mauvaise idée b/c il pourrait être difficile à lire et déboguer. Le code DRY est génial, mais pas quand il sacrifie la lisibilité. Dans un test, vous voulez vraiment être capable de voir ce qui se passe. Si vous pouvez le sécher sans sacrifier la lisibilité ou ajouter de la fragilité au test, faites-le. – WattsInABox

1

Selon vos itinéraires, les domaines n'existent plus en dehors du contexte d'un client. La requête a besoin d'un customer_id pour que les routes nommées correspondent.

La façon de le faire dans votre test est:

test "should get index" do 
    get :index, :customer_id=>joe 
end 
+4

Pour que cela fonctionne, mais pour la poste ne semble pas fonctionner. –

+0

yup, comment résolvez-vous ce problème pour poster? –

+0

+1 pour comment vous pouvez le faire avec un poste – Bastes

1

Il y a un petit bijou appelé nester qui résout ce problème exact. Il génère des méthodes qui vous donnent un domains_path et similaire comme si vos itinéraires n'étaient pas imbriqués. Lorsque vos vues et tests référence, par exemple, domain_path(domain), les itinéraires sont étendus à customer_domain_path(domain.customer, domain). Il y a aussi une aide ActionController::TestCase qui ajoute :customer_id => @domain.customer pour des méthodes telles que get, post, etc.

La valeur par défaut généré des tests fonctionnels et des vues de travail hors de la boîte avec cette approche. (Disclaimer: je l'ai écrit).

Questions connexes