34

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)

Dave Schweisguth
  • 36,475
  • 10
  • 98
  • 121
Fabian Silva
  • 705
  • 1
  • 7
  • 14
  • 2
    Seems like this is the right way. Are you sure there isn't a `before(:all)` that we aren't seeing? – zetetic Oct 29 '13 at 23:47
  • Yeah, I assumed there _was_ a `before(:all)` that you were not showing. Is that not the case? – Peter Alfvin Oct 30 '13 at 04:01
  • '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? – fontno Oct 30 '13 at 04:22
  • '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 now – Fabian Silva Oct 30 '13 at 12:14

3 Answers3

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.

Romain Paulus
  • 2,306
  • 1
  • 20
  • 20
  • 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! – Fabian Silva Nov 04 '13 at 18:53
  • 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? – slhck Sep 05 '19 at 12:55
3

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.

Peter Alfvin
  • 28,599
  • 8
  • 68
  • 106
  • I don't see their code using before(:all) though, just before. – Hakanai May 24 '17 at 03:18
  • @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. – Peter Alfvin May 27 '17 at 21:23
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
cortex
  • 5,036
  • 3
  • 31
  • 41