我正在为此服务编写测试。
def run
sort_offers(product).each do |product_code|
......
offer.update(poduct_params)
Importer::Partner.get_details(product_code).new
end
end
它正在调用服务,在某些情况下,该服务将覆盖运行offer.update(product_prams)
时保存的值。我该如何在测试中跳过服务呼叫?
这是我测试的例子
context 'is valid' do
.... .....
before do
Importer::ProductCodes(product).run
end
it ......
end
答案 0 :(得分:0)
RSpec内置了一个非常强大的存根和模拟库(rspec mocks)。
require 'spec_helper'
module Importer
class Partner
def self.get_details(product_code)
"original return value"
end
end
end
class FooService
def self.run
Importer::Partner.get_details('bar')
end
end
RSpec.describe FooService do
let(:partner_double) { class_double("Importer::Partner") }
before do
stub_const("Importer::Partner", partner_double)
allow(partner_double).to receive(:get_details).and_return 'our mocked value'
end
it "creates a double for the dependency" do
expect(FooService.run).to eq 'our mocked value'
end
end
class_double
为该类创建一个double,您可以使用.expect
和.allow
以及模拟接口来设置返回值。这非常有用,因为您可以存根new
或intialize
方法来返回double或spy。
stub_constant
将在完成规范后将常数重置为其先前的值。
那表示您可以通过在服务中使用构造函数注入来避免使用stub_constant
:
class PhotoImportService
attr_accessor :client, :username
def initialize(username, api_client: nil)
@username = username
@client = api_client || APIClient.new(ENV.fetch('API_KEY'))
end
def run
client.get_photos(username)
end
end
答案 1 :(得分:0)
我将存根Importer::Partner.get_details
返回一个对double
做出响应的new
:
context 'is valid' do
before do
allow(Importer::Partner).to receive(:get_details).and_return(double(new: nil))
end
# it ...
end
根据您的需求,您可能希望增加使用正确参数调用该模拟并且实际上也对该模拟调用了new
的期望:
context 'is valid' do
let(:mock) { double(new: nil) }
before do
allow(Importer::Partner).to receive(:get_details).and_return(double(new: nil))
end
it "calls the service" do
an_instance.run
expect(Importer::Partner).to have_received(:get_details).with(
foo: 'bar' # the arguments you would expect
)
expect(mock).to have_received(:new)
end
end