class RuboCop::Cop::RSpec::SubjectStub

Checks for stubbed test subjects.

@see robots.thoughtbot.com/don-t-stub-the-system-under-test

@example

# bad
describe Foo do
  subject(:bar) { baz }

  before do
    allow(bar).to receive(:qux?).and_return(true)
  end
end

Constants

MSG

Public Instance Methods

expectation?(node) click to toggle source
# File lib/rubocop/cop/rspec/subject_stub.rb, line 73
def expectation?(node)
  return if all_matcher?(node)
  receive_message?(node)
end
on_block(node) click to toggle source
# File lib/rubocop/cop/rspec/subject_stub.rb, line 78
def on_block(node)
  return unless example_group?(node)

  find_subject_stub(node) do |stub|
    add_offense(stub, location: :expression)
  end
end

Private Instance Methods

find_subject(node, parent: nil) { |name, parent| ... } click to toggle source

Find a subject definition

@param node [RuboCop::Node] @param parent [RuboCop::Node,nil]

@yieldparam subject_name [Symbol] name of subject being defined @yieldparam parent [RuboCop::Node] parent of subject definition

# File lib/rubocop/cop/rspec/subject_stub.rb, line 136
def find_subject(node, parent: nil, &block)
  subject(node) { |name| yield(name, parent) }

  node.each_child_node do |child|
    find_subject(child, parent: node, &block)
  end
end
find_subject_expectation(node, subject_name) { |node| ... } click to toggle source

Find a subject message expectation

@param node [RuboCop::Node] @param subject_name [Symbol] name of subject

@yield [RuboCop::Node] message expectation

# File lib/rubocop/cop/rspec/subject_stub.rb, line 105
def find_subject_expectation(node, subject_name, &block)
  # Do not search node if it is an example group with its own subject.
  return if example_group?(node) && redefines_subject?(node)

  # Yield the current node if it is a message expectation.
  yield(node) if message_expectation?(node, subject_name)

  # Recurse through node's children looking for a message expectation.
  node.each_child_node do |child|
    find_subject_expectation(child, subject_name, &block)
  end
end
find_subject_stub(node, &block) click to toggle source

Find subjects within tree and then find (send) nodes for that subject

@param node [RuboCop::Node] example group

@yield [RuboCop::Node] message expectations for subject

# File lib/rubocop/cop/rspec/subject_stub.rb, line 93
def find_subject_stub(node, &block)
  find_subject(node) do |subject_name, context|
    find_subject_expectation(context, subject_name, &block)
  end
end
redefines_subject?(node) click to toggle source

Check if node's children contain a subject definition

@param node [RuboCop::Node]

@return [Boolean]

# File lib/rubocop/cop/rspec/subject_stub.rb, line 123
def redefines_subject?(node)
  node.each_child_node.any? do |child|
    subject(child) || redefines_subject?(child)
  end
end