I have a controller spec like this :
describe "#create" do
before { post 'create', params }
context "when the artist is valid" do
before { allow(artist).to receive(:save).and_return(true) }
it { expect(page).to redirect_to(root_path) }
it { expect(notifier).to have_received(:notify) }
end
end
This is a simple spec but It doesn't work because the describe's before block is executed before the context's before block. So, the result of artist.save
is not stubed when the create action is called.
It tried to do this :
describe "first describe" do
before { puts 2 }
describe "second describe" do
before { puts 1 }
it "simple spec" do
expect(1).to eq 1
end
end
end
I see the "2" before the "1". I'm not sure but I think it was working with previous versions.
I know, I can do this :
describe "#create" do
context "when the artist is valid" do
before { allow(artist).to receive(:save).and_return(true) }
it "redirect to the root path" do
post 'create', params
expect(page).to redirect_to(root_path)
end
it "do notifications" do
post :create, params
expect(notifier).to have_received(:notify)
end
end
end
But I think it's less clean.
I found, on this page, http://rubydoc.info/github/rspec/rspec-core/RSpec/Core/Hooks#before-instance_method than the order should be this :
before(:suite) # declared in RSpec.configure
before(:all) # declared in RSpec.configure
before(:all) # declared in a parent group
before(:all) # declared in the current group
before(:each) # declared in RSpec.configure
before(:each) # declared in a parent group
before(:each) # declared in the current group
It's not the case on this example.
I'm not sure but I think it was working with older versions of rspec.
Is there a solution?
I would strongly recommend against you changing the order of hooks in rspec. That will make your app non-standard and Rails is build on standards and having things work as expected.
Everything you're describing it "as designed". Outer before blocks are always called before inner blocks.
Your example that you feel is "less clean" is the standard way to do controller specs. I actually encourage you to do it this way so that it is more maintainable/readable. It does not look unclean to me at all.
That said, there are some options:
do_post
or something similarlet
block which is initialized lazily. I would find it unlcean if it relied on other before blocks running first, but it's an option.subject
. https://www.relishapp.com/rspec/rspec-core/v/2-6/docs/subject/explicit-subject
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With