Class: RuboCop::Cop::Sidekiq::PerformAsyncStub

Inherits:
Base
  • Object
show all
Extended by:
AutoCorrector
Defined in:
lib/rubocop/cop/sidekiq/perform_async_stub.rb

Overview

Checks that ‘perform_async` calls to enqueue Sidekiq jobs are not stubbed

Examples:

# bad
allow(Foo).to receive(:perform_async)
expect(Foo).to receive(:perform_async)
expect(Foo).not_to receive(:perform_async)

# good (still invokes the real method)
allow(Foo).to receive(:perform_async).and_call_original
expect(Foo).to receive(:perform_async).with(arg).and_call_original
allow(Foo).to receive(:perform_async).and_wrap_original { |m, *args| m.call(*args) }

# good (checking enqueued jobs)
expect { subject }.to change(Foo.jobs, :count).by(n)
expect { subject }.not_to change(Foo.jobs, :count)
expect(Foo.jobs.count).to eq(n)

# good (only checks previously pre-stubbed objects)
expect(Foo).to have_received(:perform_async)

Constant Summary collapse

MSG =
"Prefer checking enqueued jobs over stubbing `perform_async`."
MSG_RECEIVE =
"Prefer checking enqueued jobs over stubbing `perform_async` or add `.and_call_original`."
RESTRICT_ON_SEND =
%i(receive).freeze

Instance Method Summary collapse

Instance Method Details

#on_send(node) ⇒ Object Also known as: on_csend



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/rubocop/cop/sidekiq/perform_async_stub.rb', line 47

def on_send(node)
  return unless stub_perform_async?(node)

  negative_expectation = false
  calls_original = false

  current = node.parent
  while current&.call_type?
    negative_expectation = true if current.method?(:not_to) || current.method?(:to_not)
    calls_original = true if current.method?(:and_call_original) || current.method?(:and_wrap_original)

    current = current.parent
  end

  return add_offense(node) if negative_expectation
  return if calls_original # already have .and_call_original, not an offense

  tail = message_expectation_chain_tail(node)
  return add_offense(node, message: MSG_RECEIVE) if tail.parent&.block_type?

  add_offense(node, message: MSG_RECEIVE) do |corrector|
    corrector.insert_after(tail, ".and_call_original")
  end
end

#stub_perform_async?(node) ⇒ Object

TODO: this should match on perform_async, not on receive, requires pattern update



43
44
45
# File 'lib/rubocop/cop/sidekiq/perform_async_stub.rb', line 43

def_node_matcher :stub_perform_async?, <<~PATTERN
  (send nil? :receive (sym :perform_async))
PATTERN