RSpec和FactoryGirl问题(避免重复代码)

时间:2013-07-19 08:15:47

标签: ruby-on-rails ruby rspec factory-bot

我实际上正在使用RSpec编写测试。以下代码位于spec/requests/tasks_spec.rb


require 'spec_helper'

describe "Tasks" do

  env_headers = {'HTTP_ACCEPT' => Mime::JSON, "devise.mapping" => Devise.mappings[:user] }

  describe "GET /tasks" do
    context "with valid credentials" do
      user = FactoryGirl.build(:user)
      authorization_header =  ActionController::HttpAuthentication::Basic.encode_credentials(user.authentication_token, nil)
      env_headers['HTTP_AUTHORIZATION'] = authorization_header

      it "should succeed" do
        get '/tasks', nil, env_headers
        response.status.should eq(200)
      end
    end

    context "with invalid credentials" do
      authorization_header = ActionController::HttpAuthentication::Basic.encode_credentials("123456", nil)
      env_headers['HTTP_AUTHORIZATION'] = authorization_header

      it "should fail" do
        get '/tasks', nil, env_headers
        response.status.should eq(401)
      end
    end

  end
end

由于我不仅要进行GET测试(但是PUT,DELETE等),我还是希望避免代码重复与用户实例化有关。如果我实际将user = FactoryGirl.build(:user)移到上下文之外,由于范围问题,我将无法访问user变量。

  • 我想知道RSpec中是否有最佳实践 使这个用户可以重用每个上下文。

  • 还有更多,但如果我可以将其仅用于特定的,则可选 诸如(在我的情况下)的上下文:context "with valid credentials" (因为我的with invalid credentials我不需要用户 上下文)。

更新:

通过使用让我仍然得到范围问题,这是由于一个愚蠢的错误。我在我的阻止之外要求一个用户。以下代码没问题:


describe "Tasks" do

  let(:user) { FactoryGirl.build(:user) }

  describe "GET /tasks" do
    context "with valid credentials" do

      it "should succeed" do
        authorization_header =  ActionController::HttpAuthentication::Basic.encode_credentials(user.authentication_token, nil)
        env_headers['HTTP_AUTHORIZATION'] = authorization_header

        get '/tasks', nil, env_headers
        response.status.should eq(200)
      end
    end

1 个答案:

答案 0 :(得分:0)

您可以将以下内容放在上下文之外:

describe "Tasks" do

  let(:user) { FactoryGirl.build(:user) }

  # your tests

let是延迟加载的,这意味着只有在执行user.a_method之类的操作时调用时才会对其进行评估,或者只是调用user

仅供参考,您可以通过添加“!”来指定RSpec直接评估let

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