Reputation: 1021
I'm currently taking Coursera's free Ruby on Rails Introduction class. I'm working on the third assignment which contains creating a People
class where you have some functionality like a search function.
I'm getting a weird error when I run rspec
with their designed unit tests. I'm 99% sure the error is lying in the unit tests. Specifically, before I've even touched any files, I'm getting the following error:
raise <<-EOS
#{description} accessed in #{article} #{hook_expression} hook at:
#{CallerFilter.first_non_rspec_line}
`let` and `subject` declarations are not intended to be called
in #{article} #{hook_expression} hook, as they exist to define state that
is reset between each example, while #{hook_expression} exists to
#{hook_intention}.
EOS
RuntimeError:
let declaration `class` accessed in an `after(:context)` hook at:
/Users/<username>/.rvm/gems/ruby-2.4.0/gems/rspec-core-3.7.1/exe/rspec:4:in `<top (required)>'
`let` and `subject` declarations are not intended to be called
in an `after(:context)` hook, as they exist to define state that
is reset between each example, while `after(:context)` exists to
cleanup state that is shared across examples in an example group.
For starters, I don't totally understand the syntax they're using to describe talking about their tests. Secondly, here is the raw testing file that the author's of the Coursera class wrote:
require 'rspec'
require 'rspec/its'
require_relative '../module2_lesson3_formative.rb'
describe "lesson3" do
context "check results" do
p1 = Person.new("Ivana", "Trump")
p2 = Person.new("Eric", "Trump")
p3 = Person.new("Melania", "Trump")
p4 = Person.new("Marla", "Maples")
it "unexpected search result" do
expect(Person.search("Trump").size).to be == 3
end
end
context "check instance properties" do
subject(:john) { Person.new("Chris", "Christie") }
it "missing first_name" do
is_expected.to respond_to(:first_name)
end
it "missing last_name" do
is_expected.to respond_to(:last_name)
end
end
context "check class properties" do
subject(:class) { Person }
it "missing search" do
is_expected.to respond_to(:search)
end
end
end
I am hoping that someone can explain to me the debugging information when I run rspec
. I'm using RSpec 3.7
which I'm guessing is the problem, as indicated that it might be a versioning upgrade thing here. That would also explain the fact that the class's authors didn't intentionally push up bad code. What is the best way for me to fix this and why are lines like this:
subject(:john) { Person.new("Chris", "Christie") }
in bad form? Thanks so much! Really appreciate your time :)
Upvotes: 1
Views: 109
Reputation: 33420
In order to change the subject class for your specs, then you can "redefine" subject per each of your examples, or as it's needed.
When trying to change the class of the spec subject, with let or subject, then you get the detailed error (warning) message:
let
andsubject
declarations are not intended to be called in anafter(:context)
hook, as they exist to define state that is reset between each example
So you can't set explicitly the class of your subject, because it'll be resetted with each running example.
You can set your subject to be a Person object within the "check class properties" context by using just subject
, this way is_expected
will check in this object that responds to the class method search, like:
context "check class properties" do
subject { Person }
it 'missing search' do
is_expected.to respond_to(:search)
end
end
Upvotes: 1
Reputation: 1021
This seems to have resolved the problem that rspec
was complaining about:
describe "lesson3" do
subject { person } # ADDED THIS LINE
context "check results" do
p1 = Person.new("Ivana", "Trump")
p2 = Person.new("Eric", "Trump")
p3 = Person.new("Melania", "Trump")
p4 = Person.new("Marla", "Maples")
it "unexpected search result" do
expect(Person.search("Trump").size).to be == 3
end
end
context "check instance properties" do
let(:person) { Person.new("Chris", "Christie") } # CHANGED THIS LINE
it "missing first_name" do
is_expected.to respond_to(:first_name)
end
it "missing last_name" do
is_expected.to respond_to(:last_name)
end
end
context "check class properties" do
let(:person) { Person } # CHANGED THIS LINE
it "missing search" do
is_expected.to respond_to(:search)
end
end
end
I still am not sure why, or what the difference is implying. I would love someone to explain it a little bit more in depth.
Upvotes: 1