假设我有一个类,它应该用不同的参数多次调用服务
class MyExecutor
def perform
targets.each do |target|
MyService.new(target).call
end
end
end
class MyService
def initialize(target)
@target = target
end
def call
@target.do_something
end
end
假设我想在MyExecutor
上编写一个测试,生成数据以使我至少有2个目标,并且我想测试在所有目标上是否适当地调用了服务MyService
。
当我只有一个目标时,我可以使用expect_any_instance_of().to receive(:call)
,但当时我并没有真正用适当的参数测试instalation,然后这种语法被否决了(此处参见注释(
describe MyExecutor
context 'with one target'
it 'calls the MyService appropriately'
expect_any_instance_of(MyService).to receive(:call)
MyExecutor.perform
end
end
end
假设我有多个目标,我如何测试MyService是否已安装两次,每个相关目标一次,并且在每个已安装的服务上,call
方法是否被适当调用测试这一点的正确方法是什么?
隐含问题:(这是解决问题的正确方法吗?(
在Rspec 3.8语法中:
describe MyExecutor do
subject(:executor) { described_class.new }
describe '#perform' do
subject(:perform) { executor.perform }
let(:target1) { instance_double('target' }
let(:target2) { instance_double('target' }
let(:service1) { instance_double(MyService, call: true) }
let(:service2) { instance_double(MyService, call: true) }
before do
allow(MyExecutor).to receive(:targets).and_return([target1, target2])
allow(MyService).to receive(:new).with(target1).and_return(service1)
allow(MyService).to receive(:new).with(target2).and_return(service2)
perform
end
it 'instantiates MyService once for each target' do
expect(MyService).to have_received(:new).with(target1).ordered
expect(MyService).to have_received(:new).with(target2).ordered
end
it 'calls MyService once for each target' do
expect(service1).to have_received(:call)
expect(service2).to have_received(:call)
end
end
end
请注意,使用.ordered
可以指定操作的确切顺序。
请注意,将MyService.with
与特定参数加倍可以控制该特定参数的返回值。
我想我理解你的需求:
describe MyExecutor do
context 'with one target' do
it 'calls the MyService appropriately' do
target1 = double("TargetClass")
target2 = double("TargetClass")
allow(MyExecutor).to receive(:targets).and_return([target1, target2])
service1 = double(MyService, call: nil)
service2 = double(MyService, call: nil)
expect(MyService).to receive(:new).with(target1).once.and_return(service1)
expect(MyService).to receive(:new).with(target2).once.and_return(service2)
MyExecutor.perform
end
end
end