如何在rspec中的测试类中存根实例化的类

Raj*_*aik 4 ruby rspec

我在插入外部api时遇到问题,以下是示例

require 'rspec'
require 'google/apis/storage_v1'

module Google
  class Storage
    def upload file
      puts '#' * 90
      puts "File #{file} is uploaded to google cloud"
    end
  end
end

class UploadWorker
  include Sidekiq::Worker

  def perform
    Google::Storage.new.upload 'test.txt'
  end
end


RSpec.describe UploadWorker do

  it 'uploads to google cloud' do
    google_cloud_instance = double(Google::Storage, insert_object: nil)
    expect(google_cloud_instance).to receive(:upload)
    worker = UploadWorker.new
    worker.perform
  end
end
Run Code Online (Sandbox Code Playgroud)

我正在尝试存根Google :: Storage类。此类在被测试的对象内实例化。如何验证此实例上的消息期望?

当我在上面的示例中运行时,我得到以下输出,这似乎合乎逻辑,我的double未被测试对象使用

(Double Google::Storage).upload(*(any args))
           expected: 1 time with any arguments
           received: 0 times with any arguments
Run Code Online (Sandbox Code Playgroud)

我是Rspec的新手,在此方面遇到困难,我们将不胜感激。

谢谢!

Grz*_*orz 6

争取DI始终是一个好主意(/sf/answers/3598096351/),但是有时由于某些原因您不能这么做,因此这是在不更改“生产”代码的情况下进行存根的另一种方法。

1。 expect_any_instance_of

it 'uploads to google cloud' do
  expect_any_instance_of(Google::Storage).to receive(:insert_object)
  worker = UploadWorker.new
  worker.perform
end
Run Code Online (Sandbox Code Playgroud)

如果您只想测试该方法是否在任何此类对象上调用了该方法。

2.更加精细的设置

如果您想控制或设置更多期望,可以执行此操作

  it 'uploads to google cloud' do
    the_double = instance_double(Google::Storage)
    expect(Google::Storage).to receive(:new).and_return(the_double)
       # + optional `.with` in case you wanna assert stuff passed to the constructor
    expect(the_double).to receive(:insert_object)
    worker = UploadWorker.new
    worker.perform
  end
Run Code Online (Sandbox Code Playgroud)

再次-依赖注入更加清晰,您应该为此而努力。这是另一种可能性。