2017-01-22 3 views
3

Je suis en train de tester une méthode de contrôleur pour créer de nouvelles commandes (application de type e-commerce). Si l'utilisateur est présent dans le système, il doit être redirigé vers new_user_session_path, sinon vers new_order_path. Aussi simple que cela.Rspec empêcher la méthode d'être appelé

Ceci est mon orders_controller.rb

def new 
     if !User.where(phone: params[:phone]).blank? && !user_signed_in? 

      redirect_to new_user_session_path() 
      flash[:info] = "Already present" 
     else 
      @order = Order.new 
      @menu = Menu.find(params[:menu_id]) 
      @menu_price = @menu.calculate_price(@menu, params) 
     end 
    end 

Dans mon application, j'ai besoin de la méthode calculate_price d'être appelé, car il calcule le prix global compte tenu des params. Mais dans mon test, je veux juste m'assurer que la redirection est correcte.

En ce moment, je reçois des erreurs comme (ils proviennent dans le fichier Menu.rb, depuis calculate_price est appelé):

Front::OrdersController#new redirects user to new order page if user is not present in the system 
    Failure/Error: menu_price_change = menu_amount.split(",")[1].gsub(" ","").gsub("]",'') 

    NoMethodError: 
     undefined method `split' for nil:NilClass 

Ceci est mon fichier de spécification:

require 'rails_helper' 


describe Front::OrdersController, type: :controller do 
    describe '#new' do 
     # Set up dummy menu 
     let (:menu) { Menu.create() } 

     it "redirects user to sign up page if user is present in the system" do 
      user = User.create(name: "Bob", password: "bobspassword", phone: "+7 (903) 227-8874") 

      get :new, params: { phone: user.phone } 
      expect(response).to redirect_to(new_user_session_path(phone: user.phone)) 
     end 

     it "redirects user to new order page if user is not present in the system" do 
      non_present_phone = "+7 (903) 227-8874"  
      get :new, params: { phone: non_present_phone, menu_id: menu.id} 
      expect(response).to redirect_to(new_order_path) 
     end 

    end 
end 

de Bien sûr, je pourrais fournir tous les paramètres, mais il y en a une grande quantité et d'ailleurs, je veux juste tester la bonne redirection. Pour autant que je sache, les mocks et les sous-marins sont utiles dans ce cas, lorsque vous voulez tester explicitement les méthodes. Mais dans mon cas, je veux - en quelque sorte - les omettre. Comment puis-je m'assurer de ce comportement?

Répondre

3

Donc, vous voulez simplement tester les redirections et les erreurs qui se sont produites lorsque la méthode calculate_price vous dérange. Pourquoi ne pas simplement talonner cette méthode? Votre fichier de spécifications pourrait être comme ceci:

require 'rails_helper' 


describe Front::OrdersController, type: :controller do 
    describe '#new' do 
     # Set up dummy menu 
     let (:menu) { Menu.create() } 

     # Check this out 
     before do 
      allow_any_instance_of(Menu).to receive(:calculate_price) 
      # or if you need certain value 
      allow_any_instance_of(Menu).to receive(:calculate_price).and_return(your_value) 
     end 

     it "redirects user to sign up page if user is present in the system" do 
      user = User.create(name: "Bob", password: "bobspassword", phone: "+7 (903) 227-8874") 

      get :new, params: { phone: user.phone } 
      expect(response).to redirect_to(new_user_session_path(phone: user.phone)) 
     end 

     it "redirects user to new order page if user is not present in the system" do 
      non_present_phone = "+7 (903) 227-8874"  
      get :new, params: { phone: non_present_phone, menu_id: menu.id} 
      expect(response).to redirect_to(new_order_path) 
     end 

    end 
end 
+0

Merci! J'essayais des syntaxes différentes, par ex. 'Menu.any_instance.stub (: date) .et_return (" ")', mais le vôtre fonctionne comme un charme! – mohnstrudel

+0

Pour la grande justice 'allow_any_instance_of' n'est pas la meilleure solution. C'est juste l'option de poids léger. Pour rendre les choses plus classe créer l'instance 'Menu', faites la demande en utilisant son identifiant comme' params ['menu_id'] '(vous l'avez déjà). Et puis stub méthode 'calculate_price' appelant pas sur une instance de' Menu', mais sur votre instance 'Menu' exactement. Il peut faire un peu plus de problèmes pour vous mais ce serait une meilleure option de toute façon. – VAD