Почему объект, созданный во время теста, исчезает во время теста (с RSPE C / Rails 5.2)? - PullRequest
0 голосов
/ 05 февраля 2020

Я проверяю доступность представлений BusinessArea в контексте вошедшего / не вошедшего в систему пользователя. В начале теста я создаю объект бизнес-области (test_ba) благодаря фабрике, которая возвращает объект.

Я 'помещаю' test_ba.id, чтобы увидеть, что он создан.

Затем я запрашиваю проверенное представление.

require 'rails_helper'

RSpec.describe BusinessArea, type: :request do
  include Warden::Test::Helpers

  describe "Business Areas pages: " do
    test_ba = FactoryBot.create(:business_area)
    puts test_ba.id
    context "when not signed in " do
      it "should propose to log in when requesting index" do
        get business_areas_path
        follow_redirect!
        expect(response.body).to include('Sign in')
      end
     it "should propose to log in when requesting show" do
        puts test_ba.id
        get business_area_path(test_ba)
        follow_redirect!
        expect(response.body).to include('Sign in')
      end
    end
    context "when signed in" do
      before do
        get "/users/sign_in"
        test_user = FactoryBot.create(:user)
        login_as test_user, scope: :user
      end
      it "should display index" do
        get business_areas_path
        expect(response).to render_template(:index)
      end
      it "should display business area" do
        puts test_ba.id
        get business_area_path(test_ba)
        expect(response).to render_template(:show)
      end
    end
  end
end

Кажется, что тест выполняется правильно, но последний шаг не выполнен из-за отсутствия записи!?! Результат возвращается:

>rspec spec/requests/business_areas_spec.rb
67
.67
..67
F

Failures:

  1) BusinessArea Business Areas pages:  when signed in should display business area
     Failure/Error: @business_area = BusinessArea.find(params[:id])

     ActiveRecord::RecordNotFound:
       Couldn't find BusinessArea with 'id'=67 
     # ./app/controllers/business_areas_controller.rb:159:in `set_business_area'
     # ./spec/requests/business_areas_spec.rb:35:in `block (4 levels) in <top (required)>'

Finished in 2.07 seconds (files took 13.05 seconds to load)
4 examples, 1 failure

Failed examples:

rspec ./spec/requests/business_areas_spec.rb:33 # BusinessArea Business Areas pages:  when signed in should display business area

Можете ли вы помочь мне найти, что с этим не так?

1 Ответ

1 голос
/ 05 февраля 2020

RSpe c имеет методы let и let!, которые создают запомненные помощники, которые вы должны использовать для настройки тестовой зависимости. let - это отложенная загрузка (блок не оценивается, пока вы не ссылаетесь на него), в то время как let! - нет.

require 'rails_helper'

RSpec.describe BusinessArea, type: :request do
  include Warden::Test::Helpers

  describe "Business Areas pages: " do
    let!(:test_ba){  FactoryBot.create(:business_area) }

    context "when not signed in " do
      it "should propose to log in when requesting index" do
        get business_areas_path
        follow_redirect!
        expect(response.body).to include('Sign in')
      end
     it "should propose to log in when requesting show" do
        puts test_ba.id
        get business_area_path(test_ba)
        follow_redirect!
        expect(response.body).to include('Sign in')
      end
    end
    context "when signed in" do
      before do
        get "/users/sign_in"
        test_user = FactoryBot.create(:user)
        login_as test_user, scope: :user
      end
      it "should display index" do
        get business_areas_path
        expect(response).to render_template(:index)
      end
      it "should display business area" do
        puts test_ba.id
        get business_area_path(test_ba)
        expect(response).to render_template(:show)
      end
    end
  end
end

Но вау! Почему мой код не работает?

В RSpe c (и в любой хорошей тестовой среде) каждый пример работает изолированно и имеет свою собственную настройку и разбор. Это включает откат базы данных или ее очистку. RSpe c даже не запускает тесты в последовательном порядке.

Запись, которую вы определяете во внешнем контексте, не будет создаваться для каждого запуска теста. После первого примера, когда БД откатывается назад, его нет.

Если вы хотите настроить что-то для каждого теста, используйте before:

require 'rails_helper'

RSpec.describe BusinessArea, type: :request do
  include Warden::Test::Helpers

  describe "Business Areas pages: " do
    before do
      @test_ba = FactoryBot.create(:user)
    end

    context "when not signed in " do
      it "should propose to log in when requesting index" do
        get business_areas_path
        follow_redirect!
        expect(response.body).to include('Sign in')
      end
     it "should propose to log in when requesting show" do
        puts @test_ba.id
        get business_area_path(test_ba)
        follow_redirect!
        expect(response.body).to include('Sign in')
      end
    end
    context "when signed in" do
      before do
        get "/users/sign_in"
        @test_user = FactoryBot.create(:user)
        login_as test_user, scope: :user
      end
      it "should display index" do
        get business_areas_path
        expect(response).to render_template(:index)
      end
      it "should display business area" do
        puts @test_ba.id
        get business_area_path(test_ba)
        expect(response).to render_template(:show)
      end
    end
  end
end

Но let / let! предпочтительнее для настройки простых зависимостей.

...