Как правильно отловить ошибки в Sidekiq worker при тестировании с помощью RSpec?

У меня есть относительно простой рабочий, который использует Excon, чтобы получить что-то из Интернета. Я пытаюсь быть хорошим тестировщиком и использую Webmock, чтобы принудительно заглушить интернет-взаимодействия, так что я фактически проверяю, что должен делать код на основе различных заглушенных взаимодействий.

Я заметил, что RSpec не отлавливает сбои, происходящие внутри рабочего процесса. Это может быть мой код, это может быть ошибка, я не уверен.

Вот простой рабочий пример (да, я знаю, что спасательное исключение — это плохо, я исправлю это дальше):

  include Sidekiq::Worker
  sidekiq_options queue: 'fetch_article_content', retry: true, backtrace: true

  def perform(url)
    begin
      Excon.get(url)
    rescue Exception => e
      Rails.logger.warn("error: #{e}")
      nil
    end
  end
end

А вот упрощенный тест RSpec:

      Sidekiq::Testing.inline!
      work = FetchArticleContentWorker.new
      work.perform("http://google.com")

При включенном Webmock это приводит к сбою Excon (видно в файле test.log):

error: Real HTTP connections are disabled. Unregistered request: ...

Тем не менее, RSpec считает, что это сработало просто отлично:

.

Finished in 0.44487 seconds (files took 5.35 seconds to load)
1 example, 0 failures

Я не уверен, что я делаю неправильно здесь. Я бы ожидал, что тот факт, что Sidekiq perform не был доведен до RSpec, как провал, но это не так.

  • Я не правильно ловлю эту ошибку?
  • Должен ли я проверять что-то в отношении статуса задания вместо того, чтобы ожидать, что RSpec поймает эту ошибку в рабочем?
  • Должен ли я делать что-то совершенно другое?

Спасибо!


person Erik Jacobs    schedule 28.07.2020    source источник


Ответы (2)


Чтобы RSpec увидел исключение, код должен вызвать исключение.

Вы можете повторно вызвать существующее исключение:

def perform(url)
  begin
    Excon.get(url)
  rescue Exception => e
    Rails.logger.warn("error: #{e}")
    raise e
  end
end

Вы можете обернуть существующее исключение в одно из ваших собственных:

class MyFancyException < StandardError; end

def perform(url)
  begin
    Excon.get(url)
  rescue Exception => e
    Rails.logger.warn("error: #{e}")
    raise MyFancyException.new(e)
  end
end

Либо работает. Оба потребуют некоторого RSpec, подобного этому:

describe Worker do
  subject(:worker) { described_class.new }

  describe "#perform" do
    subject(:perform) { worker.perform }

    let(:url) { "https://google.com" }

    it "raises exception" do
      expect { perform(url) }.to raise_error(MyFancyException)
    end
  end
end
person aridlehoover    schedule 30.07.2020

Я думаю, что с точки зрения rspec ошибки нет, потому что она захватывается/обрабатывается внутри воркера. Я ожидаю, что тест провалится, как и вы ожидаете, если вы удалите это спасение. И наоборот, вы можете проверить в тесте, чтобы увидеть, возвращает ли выполнение ненулевое значение для прохождения. Это помогает?

person geemus    schedule 29.07.2020