Rspec:如何测试在每个循环中调用 class 方法?

Rspec: How to test that on every each loop class method is called?

我目前正尝试在我的 rails worker class 中测试部分代码,如下所示(简化版);

class SenderWorker
   include Sidekiq::Worker
   sidekiq_options :retry => 5

   def perform(current_user_guid)
      Rails.logger.info "Starting for user_guid: #{current_user_guid}"
      user = User.find_by!(guid: current_user_guid)
      team = Team.find_by!(uuid: user.team.uuid)
      profiles = team.profiles 
      profiles.each do |profile|
         SenderClass.new(profile,
                         user).send(User::RECALL_USER)
      end
      Rails.logger.info "Finishing for user_guid: #{current_user_guid}"
   end
end

我写的测试就是这些,它们都通过了;

context 'when something occurs' do
  it 'should send' do
    sender = double("sender")
    allow(SenderClass).to receive(:new).with(user_profile, current_user) { sender }
    expect(sender).to receive(:send)
    expect(Rails.logger).to receive(:info).exactly(2).times

    worker.perform(user.guid)
  end
end

但是,我并未测试所有调用。有没有办法确保我测试 each do 循环中调用的所有内容。提前谢谢你。

您可以测试 :send 是否收到了预期的次数。

但我建议您使用 class 方法来封装那些链接的方法,从而简化测试。类似于:

def self.profile_send(profile, user)
  new(profile, user).send(User::RECALL_USER)
end

然后:

def perform(current_user_guid)
  Rails.logger.info "Starting for user_guid: #{current_user_guid}"
  user = User.find_by!(guid: current_user_guid)
  team = Team.find_by!(uuid: user.team.uuid)
  profiles = team.profiles 
  profiles.each do |profile|
    SenderClass.profile_send(profile, user)
  end
  Rails.logger.info "Finishing for user_guid: #{current_user_guid}"
end

现在您可以测试 SenderClass 收到 :send_profile X 次。

如果你真的想测试 newsend 方法调用,你可以为 SenderClass.send_profile 添加一个测试,但是你可以在循环外测试一次两个测试都将涵盖您想要的内容。