ruby on rails - Issue with RSpec and FactoryGirl (avoid code repetition) -


i'm writing tests using rspec. following code in spec/requests/tasks_spec.rb.

  require 'spec_helper'  describe "tasks"    env_headers = {'http_accept' => mime::json, "devise.mapping" => devise.mappings[:user] }    describe "get /tasks"     context "with valid credentials"       user = factorygirl.build(:user)       authorization_header =  actioncontroller::httpauthentication::basic.encode_credentials(user.authentication_token, nil)       env_headers['http_authorization'] = authorization_header        "should succeed"         '/tasks', nil, env_headers         response.status.should eq(200)       end     end      context "with invalid credentials"       authorization_header = actioncontroller::httpauthentication::basic.encode_credentials("123456", nil)       env_headers['http_authorization'] = authorization_header        "should fail"         '/tasks', nil, env_headers         response.status.should eq(401)       end     end    end end  

since i'm not going have tests (but put, delete, etc), avoid code repetition concerning user instantiation. if move user = factorygirl.build(:user) outside context i'll not able access user variable because of scope issue.

  • i know if there's best practice in rspec make user reusable each context.

  • and more, optional if can make usable specific contexts such (in case) : context "with valid credentials" (since don't need user with invalid credentials context).

update :

by using let still getting scope issue, , due stupid mistake. asking user outside block. following code ok :

  describe "tasks"    let(:user) { factorygirl.build(:user) }    describe "get /tasks"     context "with valid credentials"        "should succeed"         authorization_header =  actioncontroller::httpauthentication::basic.encode_credentials(user.authentication_token, nil)         env_headers['http_authorization'] = authorization_header          '/tasks', nil, env_headers         response.status.should eq(200)       end     end  

you can put following once outside context:

describe "tasks"    let(:user) { factorygirl.build(:user) }    # tests 

let lazy loaded, means evaluated each time if called in spec when doing user.a_method, or calling user.

fyi can specify rspec evaluate directly let adding "!"

let!(:foo) { 'foo' } # evaluated right away 

Comments