In RSpec, using let variable inside before :all block
Asked Answered
S

3

35

I have the following code inside most of my tests:

describe 'index'
 let(:company) { FactoryGirl.create(:company) }
 let(:user) { FactoryGirl.create(:user, company: company) }

 before do
   sign_in user
   visit products_path
 end
...
end

But I'm getting the following warning:

WARNING: let declaration 'user' accessed in a 'before(:all)'

My question is, what is the correct way of doing this? I can't find much information about the warning itself.

Thanks!

EDIT: My goal is to use the user variable so I can pass it on to sign_in, which signs the user in, and use it later on another tests (I check for the company attribute of the User)

Stoat answered 29/10, 2013 at 22:28 Comment(4)
Seems like this is the right way. Are you sure there isn't a before(:all) that we aren't seeing?Jessalin
Yeah, I assumed there was a before(:all) that you were not showing. Is that not the case?Averil
'Index' is,im guessing, not your top level describe block, is this nested in another describe or context block above it? In other words, are you sure you are not inheriting something. Also, before do is the same as before :each do. Its implied. Can you show the whole spec file?Ludewig
'Index' is the first nested describe block. It's inside another describe block, which is the first describe on the file. I'll upload the whole spec file tonight as I'm not on my computer right nowStoat
M
31

I had the same problem, I have solved it by declaring all my variables as attributes inside the before block:

describe 'index'

 before(:all) do
   @company = FactoryGirl.create(:company)
   @user = FactoryGirl.create(:user, company: @company)

   sign_in @user
   visit products_path
 end
...
end

Now you can use @user and @company inside your tests, and you shouldn't have any warnings.

Mishear answered 30/10, 2013 at 22:25 Comment(2)
Ended up doing exactly this. For some reason I don't really like the style of it, but it solves the problem for the time being. Thanks!Stoat
I found this when looking for the same issue (i.e. having to create some data for a group of tests), but it feels very hacky and quite unlike the let(...) style for the other tests. Is there no elegant solution?Symbiosis
A
4

I'm not sure what you mean by "this" in "what is the correct way of doing this"? Accessing let and subject within a before(:all) is deprecated and will be removed in RSpec 3 with the following explanation from https://github.com/rspec/rspec-core/pull/857:

let and subject declarations are not intended to be called in a before(:all) hook, as they exist to define state that is reset between each example, while before(:all) exists to define state that is shared across examples in an example group.

Averil answered 29/10, 2013 at 22:43 Comment(2)
I don't see their code using before(:all) though, just before.Gleeman
@trejkaz, per the comments on the question, I was one of a group of people wondering if there was a let in a containing describe block that wasn't shown. The poster said he'd upload the whole spec file, but I can see that they never did.Averil
M
2

Taking into account Peter's answer I think the correct way is to access the user in a before each block:

before(:each) do
  sign_in user
end
Metametabel answered 29/10, 2013 at 22:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.