2017-01-22 77 views
3

我正在測試用於創建新訂單的控制器方法(類似電子商務的應用程序)。如果系統中存在用戶,則應將其重定向到new_user_session_path,否則請重定向到new_order_path。就那麼簡單。Rspec阻止被調用的方法

這是我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 

在我的應用程序,我需要的calculate_price方法被調用,因爲它計算給出的PARAMS整體價格。但在我的測試中,我只是想確保重定向是正確的。

現在我越來越喜歡錯誤(他們的源文件Menu.rb裏面,因爲calculate_price叫):

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 

這是我的規格文件:

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 

中當然我可以提供所有的參數,但是其中有相當多的參數,除此之外,我只是想測試正確的重定向。據我所知,在這種情況下,當你想顯式地測試方法時,mocks和subs是有用的。但就我而言,我想 - 不知何故 - 省略它們。我如何確保這種行爲?

回答

3

所以你只想測試重定向和calculate_price方法執行時遇到的錯誤。你爲什麼不把這種方法存根?你的spec文件可能是這樣的:

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

Thanks!我在嘗試一些不同的語法,例如'Menu.any_instance.stub(:date).and_return(「」)',但你的作品就像一個魅力! – mohnstrudel

+0

對於偉大的正義'allow_any_instance_of'不是最好的解決方案。這只是輕量級選項。爲了讓事情更加優雅,創建'Menu'實例,使用它的ID作爲'params ['menu_id']'(你已經擁有它)了。然後存根'calculate_price'方法不是調用任何'Menu'的實例,而是調用你的'Menu'實例。它可以給你帶來更多麻煩,但無論如何這將是更好的選擇。 – VAD