如何为 Rspec 中的特定参数存根方法

how to stub a method for a specific argument in Rspec

我正在尝试存根这样的方法:

allow(Flipper).to receive(:enabled?).with(:premium_plus_features_beta).and_return(false)

但是当它遇到不同的参数时 - 它会给我这样的错误:

  #<Flipper (class)> received :enabled? with unexpected arguments
          expected: (:premium_plus_features_beta)
               got: (:non_advertiser_profile_amp, {:lawyer_id=>4469860})
       Diff:
       @@ -1,2 +1,2 @@
       -[:premium_plus_features_beta]
       +[:non_advertiser_profile_amp, {:lawyer_id=>4469860}]

我通常不会打这么多桩,但为什么当我明确告诉它参数时,为什么它会在不同的参数上出错?他们显然不一样。这只是一些语法问题吗?

编辑 1

我试过了但是没用 https://makandracards.com/makandra/30543-rspec-only-stub-a-method-when-a-particular-argument-is-passed

Flipper.should_receive(:enabled?).and_call_original
Flipper.should_receive(:enabled?).with(:premium_plus_features_beta).and_return(false)

有效答案是:

allow(Flipper).to receive(:enabled?).and_call_original
allow(Flipper).to receive(:enabled?).with(:premium_plus_features_beta).and_return(false)

网上有一堆不好的信息哈哈

当使用特定参数对方法进行存根时,您只是用那些特定参数对特定方法调用进行存根。对该方法的所有其他调用都将失败并显示错误:

 #<Foo (class)> received :bar with unexpected arguments

正如 OP 所发现的那样,这里的解决方案是首先使用 and_call_through 方法对对象的所有调用进行存根,然后使用您希望存根的特定参数对特定调用进行存根。

根据 OP 的回答,第一行存根所有对 Flipper 对象的调用并允许它们调用底层代码,第二行存根接收 :premium_plus_features_beta 和 [=34= 的调用] false:

allow(Flipper).to receive(:enabled?).and_call_original
allow(Flipper).to receive(:enabled?).with(:beta).and_return(false)

此外,还有一点需要说明。 OP 问题中的代码使用了 OLD RSpec 期望语法。 OP 答案中的代码使用新的 RSpec 存根语法。所以,当代码这样说时:

Flipper.should_receive(:enabled?).and_call_original
Flipper.should_receive(:enabled?).with(:beta).and_return(false)

它在做什么:

expect(Flipper).to have_received(:enabled?).and_call_original
expect(Flipper).to have_received(:enabled?).with(:beta).and_return(false)

这与我认为 OP 真正想要做的完全不同:

before do
  allow(Flipper).to receive(:enabled?).and_call_original
  allow(Flipper).to receive(:enabled?).with(:beta).and_return(enabled?)
end

context "when the beta is disabled" do 
  let(:enabled?) { false }

  it "hides the beta" do
    ...
  end
end

context "when the beta is enabled" do 
  let(:enabled?) { true }

  it "shows the beta" do
    ...
  end
end
    

最后,对于那些好奇为什么 RSpec 更改语法的人...旧语法需要在 Object 上进行猴子补丁才能添加 should_receive 方法。我认为 RSpec 团队更喜欢新语法,因为它不再需要猴子补丁。