【问题标题】:Rspec test public controller method passing params to private controller methodRspec测试公共控制器方法将参数传递给私有控制器方法
【发布时间】:2015-06-18 18:33:09
【问题描述】:

这是我的控制器:

class PlansController

  def use_new_card
    @user = User.find_by_id(new_card_params[:user_id])
    if new_stripe_card
    ...
  end

  private

  def new_card_params
    params.permit(:user_id, :stripeToken)
  end

  def new_stripe_card
    StripeService.new({user_id: @user.id, customer_id: @user.stripe_customer_id, source: new_card_params[:stripeToken]}).new_card
  end
end

我正在尝试编写一个控制器规范,测试当 use_new_card 方法的正确参数为 POST 时,new_stripe_cardStripeService.new 会正确获取这些参数。

到目前为止,我的规范看起来像这样:

describe "when proper params are passed" do
  before do
    @user = User.create(...)
  end

  it "should allow StripeService.new to receive proper parameters" do
    StripeService.should_receive(:new).with({user_id: @user.id, customer_id: @user.stripe_customer_id, source: "test"})
    post :use_new_card, user_id: @user.id, stripeToken: "test"
  end
end

但是我得到了

Failure/Error: post :use_new_card, user_id: @user.id, stripeToken: "test"
 NoMethodError:
   undefined method `new_card' for nil:NilClass

完全公平,但我不知道如何解决这个问题...我不能只存根 new_card,因为 nil 对象上的存根方法仍会引发此错误(我尝试添加 @987654330 @已经进入before块)

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-4 rspec controller rspec-rails


    【解决方案1】:

    存根方法默认返回nil。使用and_return 指定存根返回的值::

    StripeService.should_receive(:new).and_return(whatever)
    

    或使用较新的语法

    expect(StripeService).to receive(:new).and_return(whatever)
    

    编辑

    请原谅我挥手。您的存根必须返回一个对象,该对象将在测试所需的范围内充当StripeService 的实例。比如:

    let(:new_card) { double }
    let(:new_stripe_service) { double(new_card: new_card) }
    ...
    expect(StripeService).to receive(:new).and_return(new_stripe_service)
    

    现在,当测试引用new_stripe_service 时,RSpec 将返回一个测试替身,其中包含一个名为#new_card 的方法存根,它本身就是一个替身。您可以添加使测试通过所需的任何其他存根。或者,您可以为new_stripe_service 返回一个StripeService 的实际实例。

    【讨论】:

    • 如果我添加and_return(new_card),因为这是应该调用的方法的名称,我会收到此错误:Failure/Error: StripeService.should_receive(:new).with({user_id: @user.id, customer_id: "test_customer", source: "test"}).and_return(new_card) NameError: undefined local variable or method new_card' for #<:examplegroups::planscontrollerusenewcard::whenproperparametersarepassed :0x007f8aad94b2b0>`
    • 哦,是的,这帮助很大。就我个人而言,我对let 不够满意,但从未真正使用过它,但我可以通过@SSnew = StripeService.new({})expect(StripeService).to receive(:new).and_return(@SSnew) 轻松做到这一点。谢谢!!!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-15
    • 1970-01-01
    • 1970-01-01
    • 2020-05-19
    • 2014-07-21
    相关资源
    最近更新 更多