Rails RSpec中如何测试Job的perform方法执行无异常且不依赖Service内部逻辑
解决方案
有两种可落地的实现方案,都可以满足校验Job执行无参数错误、不需要依赖Service内部实现的需求:
方案1:校验Service初始化参数与调用逻辑
直接校验DoSomethingJob#perform调用Service的参数匹配度,仅stub业务执行的call方法,不跳过initialize的参数校验:
require 'spec_helper' describe DoSomethingJob do # 原有入队校验用例可保留,补充参数校验后更严谨 it '正确入队' do expect { described_class.perform_later(a, b, c) }.to have_enqueued_job.with(a, b, c) end it '调用Service时参数匹配无错误' do # 写法1:仅stub call方法,initialize会正常执行参数校验 # allow_any_instance_of(Service).to receive(:call) # 写法2:更严谨的参数校验写法,无需依赖Service内部实现 service_double = instance_double(Service) expect(Service).to receive(:new).with(a, b, c).and_return(service_double) expect(service_double).to receive(:call) expect { described_class.new.perform(a, b, c) }.not_to raise_error end end
如果Service的initialize参数发生变更,第二种写法的expect(Service).to receive(:new).with(a,b,c)会直接断言失败,刚好能捕获参数不匹配的问题。
方案2:端到端校验入队+执行流程
借助RSpec Active Job的perform_enqueued_jobs辅助方法,模拟真实执行流程,覆盖入队、反序列化、执行全流程的参数校验:
require 'spec_helper' describe DoSomethingJob do it '入队后执行无报错' do service_double = instance_double(Service) allow(Service).to receive(:new).with(a, b, c).and_return(service_double) allow(service_double).to receive(:call) expect { described_class.perform_later(a, b, c) perform_enqueued_jobs }.not_to raise_error end end
两种方案都不需要关心Service内部的业务实现,仅校验Job和Service的调用契约,和Service本身的单元测试完全解耦。
内容的提问来源于stack exchange,提问作者Johann Esburgo
相关产品推荐
相关产品推荐

