【问题标题】:Rspec prevent method from being calledRspec 防止方法被调用
【发布时间】:2017-06-07 02:07:11
【问题描述】:

我正在测试一种用于创建新订单的控制器方法(类似电子商务的应用程序)。如果用户在系统中,他应该被重定向到new_user_session_path,否则到new_order_path。就这么简单。

这是我的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 方法,因为它计算给定参数的总价格。但在我的测试中,我只想确保重定向是正确的。

现在我遇到了类似的错误(它们来自 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

当然,我可以提供所有参数,但它们的数量非常多,此外,我只想测试正确的重定向。据我所知,在这种情况下,当您想显式测试方法时,mock 和 subs 很有用。但就我而言,我想 - 不知何故 - 省略它们。我怎样才能确保这种行为?

【问题讨论】:

    标签: ruby-on-rails ruby rspec mocking stub


    【解决方案1】:

    因此,您只想测试重定向,并且执行 calculate_price 方法时发生的错误会打扰您。你为什么不直接存根那个方法呢?你的规范文件可能是这样的:

    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
    

    【讨论】:

    • 谢谢!我正在尝试一些不同的语法,例如Menu.any_instance.stub(:date).and_return(""),但你的作品就像一个魅力!
    • 为了伟大的正义allow_any_instance_of 不是最好的解决方案。这只是轻量级的选择。为了让事情更优雅,创建Menu 实例,使用它的ID 作为params['menu_id'] 发出请求(你已经有了它)。然后存根calculate_price 方法调用不是Menu 的任何实例,而是你的Menu 实例。它可能会给您带来更多麻烦,但无论如何它会是更好的选择。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-12
    • 1970-01-01
    • 2012-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-15
    相关资源
    最近更新 更多