如何在Rspec中为特定参数存根一个方法

3
我将尝试这样模拟一个方法:

我正在尝试模拟一个方法,如下所示:

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)

看这个https://relishapp.com/rspec/rspec-mocks/v/2-4/docs/method-stubs。你可以添加任意数量的参数:`.with(:premium_plus_features_beta, :non_advertiser_profile_amp)`。 - undefined
2个回答

7

当使用特定参数对方法进行存根处理时,您仅对具有这些特定参数的具体方法调用进行存根处理。对该方法的所有其他调用都将失败,并出现以下错误:

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

如OP所发现的,这里的解决方案是先使用and_call_through方法拦截对象的所有调用,然后再使用特定参数来拦截特定调用。
根据OP的答案,第一行拦截了Flipper对象的所有调用,并允许它们调用底层代码;第二行拦截了接收:premium_plus_features_beta的调用,并返回false
allow(Flipper).to receive(:enabled?).and_call_original
allow(Flipper).to receive(:enabled?).with(:beta).and_return(false)

另外,这里还有一个需要指出的问题,在OP问题中使用的是旧版的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)

这与我认为的原问题完全不同:
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 团队更喜欢新语法,因为它不再需要猴子补丁。


1

工作答案是:

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

互联网上有很多错误的信息,哈哈


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接