ruby - 如何在 rspec 中的测试类中实例化 stub 类

标签 ruby rspec

我在 stub 外部 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

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

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

(Double Google::Storage).upload(*(any args))
           expected: 1 time with any arguments
           received: 0 times with any arguments

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

谢谢!

最佳答案

获取 DI 始终是一个好主意 (https://stackoverflow.com/a/51401376/299774),但有时您不能这样做的原因有很多,所以这里有另一种方法可以在不更改“生产”代码的情况下对其进行 stub 。

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

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

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

同样 - 依赖注入(inject)更清晰,您应该以此为目标。这是另一种可能性。

关于ruby - 如何在 rspec 中的测试类中实例化 stub 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51401247/

相关文章:

ruby-on-rails - Rspec/Guard/FactoryGirl 返回错误 'undefined method' 错误

ruby - Ruby 中 "return x if x"的简写

ruby-on-rails - 如何正确使用具有唯一性验证的 shoulda 匹配器?

ruby-on-rails - rails 更新 crud View

Ruby gem 环境问题 - LoadError : no such file to load -- robots

ruby-on-rails - 如果没有可用标签,则运行标记规范或全部

ruby-on-rails-3 - 升级到 RSpec 2 : errors replaced with have(n). errors_on?需要解决方法

ruby-on-rails - 在 RSpec 中使用 expect 和 should

ruby-on-rails - sidekiq 停止时,由 sidekiq 生成的进程也会停止

ruby-on-rails - FactoryGirl 序列破坏了我的 rspec 测试(我认为)