Hello

A `subject` is just a special instance of `let`.

It is intended to give attention to the “subject” under test, originally it had 
some special powers as you note (such as the implicit subject, and chaining 
matchers of that as `is_expected.to matcher`) but those remain as syntactic 
sugar only really.

We advocate that you at least name your subject (as you have), 
`subject(:person)` and then use it either implicitly (as `is_expected.to` or 
explicitly as its name, e.g. `expect(person).to`.

Its value really depends on how you use it, as it is shared between various 
tests in a context, it should be the common value for that context.

Personally I just use a let.

Hope that helps.
Jon Rowe
---------------------------
[email protected]
jonrowe.co.uk

On 28 November 2018 at 16:32, Alexander Popov wrote:
> 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:
>
> relishapp.com/rspec/rspec-core/v/3-8/docs/subject/implicitly-defined-subject 
> (https://relishapp.com/rspec/rspec-core/v/3-8/docs/subject/implicitly-defined-subject)
>
>
> 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/dejalu-192-091d8894-a4a0-4fa5-91af-ebcee5f9a362%40jonrowe.co.uk.
For more options, visit https://groups.google.com/d/optout.

Reply via email to