RSpec 存根抛出错误数量的参数错误

RSpec stub throws wrong number of arguments error

我正在尝试使用新语法对 Slack gem 进行存根(旧语法会引发相同的错误):

before :each do
    allow(Slack).to receive(:channels_join).and_return(true)
end

这一行抛出 wrong number of arguments (2 for 1)。将行分成几部分,似乎对 .to 的调用引发了错误:

a = allow(Slack)
b = receive(:channels_join)
c = b.and_return(true)
a.to(c)

将参数更改为 .to 没有任何改变:

a.to(c, c)

抛出相同的 2 for 1 错误。

a.to(5)

抛出一个合理的错误:only the receive or receive_messages matchers are supported with allow(...).to, but you have provided: 5

为什么会抛出 2 for 1 错误?

如果您启用了 verify_partial_doubles 选项,那么 RSpec 将在您存根时检查 Slack 是否响应 :channels_join。不幸的是,Slack.respond_to?implemented incorrectly:

def self.respond_to?(method)
  return client.respond_to?(method) || super
end

问题是 Object#respond_to? accepts two arguments(多年来,至少从 1.8.7 开始,如果不是更早的话!),并且 RSpec 传递了第二个参数,期待respond_to? 将接受两个参数,因为它应该接受。

要修复它,您可以(暂时)猴子修补松弛 gem:

module Slack
  def self.respond_to?(method, include_all=false)
    return client.respond_to?(method, include_all) || super
  end
end

不过,这确实应该在 slack gem 中得到修复,因此我鼓励您与维护人员就此修复打开一个 PR。

更广泛地说,当您 运行 遇到此类错误时,您可以通过传递 rspec -b(或 --backtrace)标志来了解有关该问题的更多信息,这将打印完整的回溯。在您的情况下,我希望它显示 RSpec 中的 respond_to? 调用站点和 Slack 定义 respond_to? 仅接受一个参数的行。然后你可以查看这些行来弄清楚发生了什么。