Hello,

Given a class:

class Person
  def name
    'John'
  end

  def age
    20
  end
end


what is the proper way to use subject?

Version 1:

RSpec.describe Person do
  subject(:person) { Person.new }

  it '#name' do
    expect(person.name).to eq 'John'
  end

  it '#age' do
    expect(person.age).to eq 20
  end
end

Version 2:

RSpec.describe Person do
  let(:person) { Person.new }

  describe '#name' do
    subject { person.name }

    it { is_expected.to eq 'John' }
  end

  describe '#age' do
    subject { person.age }

    it { is_expected.to eq 20 }
  end
end

I think that most people have the very deeply-rooted belief that subject 
necessarily needs to hold an instance of the class under test (Version 1). 
This might partly come from this passage in the documentation:

https://relishapp.com/rspec/rspec-core/v/3-8/docs/subject/implicitly-defined-subject

> If the first argument to the outermost example group is a class, an 
instance of that class is exposed to each example via the subject method.

However, I think that here the documentation simply describes what the 
default behavior is and doesn't imply that it always has to be that way. My 
understanding is that subject conceptually represents the thing under 
testing. If we want to assert the result of a method call, than subject 
better hold this result. For example, again given a class:

class Person
  attr_accessor :name

  def initialize(name)
    @name = name
  end

  def greeting
    "Hi, #{name}!"
  end
end

I find it more appropriate to use subject like so:

RSpec.describe Person do
  describe '#greeting' do
    context 'when the person is called John' do
      subject { Person.new('John').greeting }

      it { is_expected.to eq 'Hi, John!' }
    end

    context 'when the person is called Merry' do
      subject { Person.new('Merry').greeting }

      it { is_expected.to eq 'Hi, Merry!' }
    end
  end
end

instead of:

RSpec.describe Person do
  subject(:person) { Person.new(name) }

  describe '#greeting' do
    context 'when the person is called John' do
      let(:name) { 'John' }

      it { expect(subject.greeting).to eq 'Hi, John!' }
    end

    context 'when the person is called Merry' do
      let(:name) { 'Merry' }

      it { expect(subject.greeting).to eq 'Hi, Merry!' }
    end
  end
end

I'd like to know what is the recommended way of using subject. Thank you 
very much.

-- 
You received this message because you are subscribed to the Google Groups 
"rspec" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/rspec/e3010c8b-8631-404e-9c84-2591b0217a34%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to