我在rails app中测试我的一名工作人员时遇到问题。它看起来像这样:
class UserStatisticsWorker
include Sidekiq::Worker
include Sidetiq::Schedulable
def perform(administration_id = nil)
administrations(administration_id).find_each do |administration|
User::StatisticsCalculator.new.recalculate_if_needed(administration.id)
end
end
private
def administrations(administration_id = nil)
administration_id.present? ? Administration.where(id: administration_id) : Administration.all
end
end
用rspec测试它:
require 'spec_helper'
describe UserStatisticsWorker do
describe 'perform' do
let!(:administration) { create(:administration) }
let!(:administration_2) { create(:administration) }
context 'when administration_id is present' do
it 'runs User::StatisticsCalculator for one administration' do
expect_any_instance_of(User::StatisticsCalculator).to receive(:recalculate_if_needed).once
subject.perform(administration.id)
end
end
context 'when administration_id is not present' do
it 'runs User::StatisticsCalculator for all administrations' do
expect_any_instance_of(User::StatisticsCalculator).to receive(:recalculate_if_needed).twice
subject.perform
end
end
end
end
第二个规范未通过以下错误:
The message 'recalculate_if_needed' was received by #<User::StatisticsCalculator:85721520 > but has already been received by #<User::StatisticsCalculator:0x0000000a383498>
为什么?
答案 0 :(得分:1)
非常良好的做法是避免使用any_instance_of,而是在工作中提取私有方法,这些方法可以更容易地进行测试。重构看起来像这样:
class UserStatisticsWorker
include Sidekiq::Worker
include Sidetiq::Schedulable
def perform(administration_id = nil)
administrations(administration_id).find_each do |administration|
recalculate_if_needed(administration)
end
end
private
def recalculate_if_needed(administration)
User::StatisticsCalculator.new.recalculate_if_needed(administration.id)
end
def administrations(administration_id = nil)
administration_id.present? ? Administration.where(id: administration_id) : Administration.all
end
end
然后,像这样测试:
require 'spec_helper'
describe UserStatisticsWorker do
describe 'perform' do
let!(:administration) { create(:administration) }
let!(:other_administration) { create(:administration) }
context 'when administration_id is present' do
it 'tries to recalculate for the specific administration' do
expect(subject).to receive(:recalculate_if_needed).once
subject.perform(administration.id)
end
end
context 'when administration_id is not present' do
it 'tries to recalculate for all administrations' do
expect(subject).to receive(:recalculate_if_needed).twice
subject.perform
end
end
end
end
答案 1 :(得分:1)
问题是你已经在一个实例上设置了两次发生的期望......但实际发生的是它在两个不同的实例上被调用了一次。
即这不是您期待的期望......
请参阅另一个答案,了解您可以尝试的内容。