使用 rspec 测试服务对象作业
Testing a service object job with rspec
我有以下工作:
class Test::MooJob < ApplicationJob
queue_as :onboarding
def perform
avariable = Test::AragornService.build("a").call
if avariable.status == true
puts "job succeeded"
end
end
end
服务如下所示:
module Test
class AragornService
def self.build(x)
self.new(x)
end
def initialize(x)
@x = x
end
def call
10.times do
Rails.logger.info @x
end
return ServiceResult.new :status => true, :message => "Service Complete", :data => @x
rescue => e
Bugsnag.notify(e, :context => 'service')
return ServiceResult.new :status => false, :message => "Error occurred - #{e.message}"
end
end
end
我正在尝试使用以下规范对其进行测试:
# bundle exec rspec spec/jobs/test/moo_job_spec.rb
require "rails_helper"
describe Test::MooJob do
subject(:job) { described_class.perform_later }
subject(:job_now) { described_class.perform_now }
let(:key) { "a" }
it 'queues the job' do
ActiveJob::Base.queue_adapter = :test
expect { job }.to have_enqueued_job(described_class)
.on_queue("onboarding")
end
it 'calls the aragorn service once' do
allow(Test::AragornService.new(key)).to receive(:call).and_return(ServiceResult.new(:status => true))
expect_any_instance_of(Test::AragornService).to receive(:call).exactly(1).times
job_now
end
end
为什么变量值保持 returning nil
我收到以下错误 "undefined method `status' for nil:NilClass"
然而,当我 return 一个简单的布尔值时,
allow(Test::AragornService.new(key)).to receive(:call).and_return(true)
它将变量值设置为真
这是服务结果 class:
class ServiceResult
attr_reader :status, :message, :data, :errors
def initialize(status:, message: nil, data: nil, errors: [])
@status = status
@message = message
@data = data
@errors = errors
end
def success?
status == true
end
def failure?
!success?
end
def has_data?
data.present?
end
def has_errors?
errors.present? && errors.length > 0
end
def to_s
"#{success? ? 'Success!' : 'Failure!'} - #{message} - #{data}"
end
end
这是因为您只是在您的规范中对 Test::AragornService
的不相关实例设置期望:
allow(Test::AragornService.new(key)).to
receive(:call).and_return(ServiceResult.new(:status => true))
这不会影响 Test::AragornService.build
创建的实例
class Test::MooJob < ApplicationJob
queue_as :onboarding
def perform
avariable = Test::AragornService.build("a").call
if avariable.status == true
puts "job succeeded"
end
end
end
你可以通过将 Test::AragornService.build
存入 return 来解决这个问题:
double = instance_double("Test::AragornService")
allow(double).to receive(:call).and_return(ServiceResult.new(status: true))
# bundle exec rspec spec/jobs/test/moo_job_spec.rb
require "rails_helper"
describe Test::MooJob do
let(:perform_later) { described_class.perform_later }
let(:perform_now ) { described_class.perform_now }
let(:service) { instance_double("Test::AragornService") }
before do
# This injects our double instead when the job calls Test::AragornService.build
allow(Test::AragornService).to receive(:build).and_return(service)
end
it 'queues the job' do
# this should be done in `rails_helper.rb` or `config/environments/test.rb` not in the spec!
ActiveJob::Base.queue_adapter = :test
expect { perform_later }.to have_enqueued_job(described_class)
.on_queue("onboarding")
end
it 'calls the aragorn service once' do
expect(service).to receive(:call).and_return(ServiceResult.new(status: true))
perform_now
end
end
我有以下工作:
class Test::MooJob < ApplicationJob
queue_as :onboarding
def perform
avariable = Test::AragornService.build("a").call
if avariable.status == true
puts "job succeeded"
end
end
end
服务如下所示:
module Test
class AragornService
def self.build(x)
self.new(x)
end
def initialize(x)
@x = x
end
def call
10.times do
Rails.logger.info @x
end
return ServiceResult.new :status => true, :message => "Service Complete", :data => @x
rescue => e
Bugsnag.notify(e, :context => 'service')
return ServiceResult.new :status => false, :message => "Error occurred - #{e.message}"
end
end
end
我正在尝试使用以下规范对其进行测试:
# bundle exec rspec spec/jobs/test/moo_job_spec.rb
require "rails_helper"
describe Test::MooJob do
subject(:job) { described_class.perform_later }
subject(:job_now) { described_class.perform_now }
let(:key) { "a" }
it 'queues the job' do
ActiveJob::Base.queue_adapter = :test
expect { job }.to have_enqueued_job(described_class)
.on_queue("onboarding")
end
it 'calls the aragorn service once' do
allow(Test::AragornService.new(key)).to receive(:call).and_return(ServiceResult.new(:status => true))
expect_any_instance_of(Test::AragornService).to receive(:call).exactly(1).times
job_now
end
end
为什么变量值保持 returning nil 我收到以下错误 "undefined method `status' for nil:NilClass"
然而,当我 return 一个简单的布尔值时,
allow(Test::AragornService.new(key)).to receive(:call).and_return(true)
它将变量值设置为真
这是服务结果 class:
class ServiceResult
attr_reader :status, :message, :data, :errors
def initialize(status:, message: nil, data: nil, errors: [])
@status = status
@message = message
@data = data
@errors = errors
end
def success?
status == true
end
def failure?
!success?
end
def has_data?
data.present?
end
def has_errors?
errors.present? && errors.length > 0
end
def to_s
"#{success? ? 'Success!' : 'Failure!'} - #{message} - #{data}"
end
end
这是因为您只是在您的规范中对 Test::AragornService
的不相关实例设置期望:
allow(Test::AragornService.new(key)).to
receive(:call).and_return(ServiceResult.new(:status => true))
这不会影响 Test::AragornService.build
class Test::MooJob < ApplicationJob
queue_as :onboarding
def perform
avariable = Test::AragornService.build("a").call
if avariable.status == true
puts "job succeeded"
end
end
end
你可以通过将 Test::AragornService.build
存入 return 来解决这个问题:
double = instance_double("Test::AragornService")
allow(double).to receive(:call).and_return(ServiceResult.new(status: true))
# bundle exec rspec spec/jobs/test/moo_job_spec.rb
require "rails_helper"
describe Test::MooJob do
let(:perform_later) { described_class.perform_later }
let(:perform_now ) { described_class.perform_now }
let(:service) { instance_double("Test::AragornService") }
before do
# This injects our double instead when the job calls Test::AragornService.build
allow(Test::AragornService).to receive(:build).and_return(service)
end
it 'queues the job' do
# this should be done in `rails_helper.rb` or `config/environments/test.rb` not in the spec!
ActiveJob::Base.queue_adapter = :test
expect { perform_later }.to have_enqueued_job(described_class)
.on_queue("onboarding")
end
it 'calls the aragorn service once' do
expect(service).to receive(:call).and_return(ServiceResult.new(status: true))
perform_now
end
end