class RuboCop::Cop::RSpec::SubjectStub

Checks for stubbed test subjects.

@see robots.thoughtbot.com/don-t-stub-the-system-under-test @see samphippen.com/introducing-rspec-smells-and-where-to-find-them#smell-1-stubject @see github.com/rubocop-hq/rspec-style-guide#dont-stub-subject

@example

# bad
describe Article do
  subject(:article) { Article.new }

  it 'indicates that the author is unknown' do
    allow(article).to receive(:author).and_return(nil)
    expect(article.description).to include('by an unknown author')
  end
end

# good
describe Article do
  subject(:article) { Article.new(author: nil) }

  it 'indicates that the author is unknown' do
    expect(article.description).to include('by an unknown author')
  end
end

Constants

MSG

Public Instance Methods

on_top_level_group(node) click to toggle source
# File lib/rubocop/cop/rspec/subject_stub.rb, line 91
def on_top_level_group(node)
  @explicit_subjects = find_all_explicit_subjects(node)

  find_subject_expectations(node) do |stub|
    add_offense(stub)
  end
end

Private Instance Methods

find_all_explicit_subjects(node) click to toggle source
# File lib/rubocop/cop/rspec/subject_stub.rb, line 101
def find_all_explicit_subjects(node)
  node.each_descendant(:block).with_object({}) do |child, h|
    name = subject(child)
    next unless name

    outer_example_group = child.each_ancestor.find do |a|
      example_group?(a)
    end

    h[outer_example_group] ||= []
    h[outer_example_group] << name
  end
end
find_subject_expectations(node, subject_names = []) { |node| ... } click to toggle source
# File lib/rubocop/cop/rspec/subject_stub.rb, line 115
def find_subject_expectations(node, subject_names = [], &block)
  subject_names = @explicit_subjects[node] if @explicit_subjects[node]

  expectation_detected = (subject_names + [:subject]).any? do |name|
    message_expectation?(node, name)
  end
  return yield(node) if expectation_detected

  node.each_child_node do |child|
    find_subject_expectations(child, subject_names, &block)
  end
end