如何使用 rspec-mock 存根第三方对象?

How to stub a third party object using rspec-mock?

我对 rspec-mock 有点陌生,现在我正在集成 hominid 以与 Mailchimp 通信,我想存根一些方法调用,所以我的请求实际上并没有转到 Mailchimp .这是我正在做的

config/initilizers/mailchimp.rb

MAILCHIMP = Hominid::API.new(ENV['MAILCHIMP_API_KEY'])
LIST_ID   = ENV['MAILCHIMP_LIST_ID']

user.rb

class User < ActiveRecord::Base
  before_create :add_subscription
  private
    def add_subscription
      MAILCHIMP.list_subscribe(LIST_ID, .......) # Some params following
    end
end

因此,如您所见,对于每个创建的用户,list_subscribe 将在 MAILCHIMP 上调用,现在我不希望 list_subscribe 实际上在每个测试中都被调用,因为 User 无处不在,所以我在全局配置了一个这样的存根:

spec/spec_helper.rb

RSpec.configure do |config|
  config.before(:each) do
    allow_any_instance_of(Hominid::API).to receive(:list_subscribe).and_return(true)
  end
end

我预计 MAILCHIMP 实例不会调用 list_subscribe,而只会调用 return true,因为如果调用 list_subscribe,一些意外的请求将会发生到 Mailchimp,我想阻止这种情况。但是我上面的代码不起作用,我错了什么?如何解决这个问题?

此外,答案可能与我这里的情况相似How should I stub a method globally using RSpec?

我很感激任何帮助和建议?谢谢!

您在 config.before(:each) do 中包含的代码将在每次测试之前执行 - 很快。但是,您的初始化代码将在执行任何测试用例之前执行一次。

这意味着存储在 MAILCHIMP 中的 Hominid::API 实例不受存根 Hominid::API.new 指令的影响 - 它仍然可以正常运行。

您也应该将存根放在 MAILCHIMP 上:

config.before(:each) do
  allow_any_instance_of(Hominid::API).to receive(:list_subscribe).and_return(true)
  allow(MAILCHIMP).to receive(:list_subscribe).and_return(true)
end