我在 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/