Arhn - архитектура программирования

Передача переменной между несколькими контекстами с помощью Rspec

Я пишу несколько тестов, используя FactoryGirl и Rspec.

spec/factories/students.rb:

FactoryGirl.define do
  factory :student do
  end

  factory :student_with_profile_and_identity, class: 'Student' do
    after(:create) do |student|
      create(:profile, profileable: student)
      create(:student_identity, student: student)
    end
  end
end

spec/factories/profiles.rb:

FactoryGirl.define do
  factory :profile do
    birthday { Faker::Date.birthday(15, 150) }
    sequence(:email) { |i| "profile_#{i}@email.com" }
    first_name { Faker::Name.first_name }
    last_name { Faker::Name.first_name }
    password { Faker::Internet.password(6, 72, true, true) }
  end
end

spec/factories/student_identities.rb:

FactoryGirl.define do
  factory :student_identity do
    provider { ['facebook.com', 'google.com', 'twitter.com'].sample }
    uid { Faker::Number.number(10) }
  end
end

spec/requests/authorizations_spec.rb:

require 'rails_helper'

RSpec.describe 'Authorizations', type: :request do
  describe 'POST /v1/authorizations/sign_in' do
    let!(:student) { create(:student_with_profile_and_identity) }

    context 'when the request is valid' do
      subject do
        post '/v1/authorizations/sign_in',
             params: credentials
      end

      context "user signs up via social network" do
        let(:credentials) do
          {
            authorization: {
              student: {
                profile_attributes: {
                  email: student.profile.email
                },
                student_identities_attributes: {
                  provider: student.student_identities[0].provider,
                  uid: student.student_identities[0].uid
                }
              }
            }
          }
        end

        it 'returns an authentication token' do
          subject
          p "1 student.profile.inspect #{student.profile.inspect}"
          expect(json['token']).to(be_present)
        end
      end

      context 'when the user has already an account' do
        let(:credentials) do
          {
            authorization: {
              email: student.profile.email,
              password: student.profile.password
            }
          }
        end

        it 'returns an authentication token' do
          p "2 student.profile.inspect #{student.profile.inspect}"
          subject
          expect(json['token']).to(be_present)
        end
      end
    end
  end
end

Почти все тесты проходят... проблема в том, что:

Он создает нового студента в каждом контексте. Я ожидаю, что let!(:student) { ... } будет чем-то вроде "singleton", другими словами, как только он будет создан/определен здесь let!(:student) { create(:student_with_profile_and_identity) }, он больше не будет вызываться.

Пример: логи такие:

"1 student.profile.inspect #<Profile id: 1, email: \"[email protected]\", profileable_type: \"Student\", profileable_id: 1>"

"2 student.profile.inspect #<Profile id: 2, email: \"[email protected]\", profileable_type: \"Student\", profileable_id: 2>"

Хотя я ожидаю, что экземпляры будут одинаковыми.

Я что-то упускаю?


Ответы:


1

В RSpec let и let! являются то же самое, за исключением того, что let ленив, а let! нетерпелив:

Используйте let для определения запоминаемого вспомогательного метода. Значение будет кэшировано для нескольких вызовов в одном и том же примере, но не для разных примеров.

Обратите внимание, что let оценивается отложенно: он не оценивается до первого вызова определяемого им метода. Вы можете использовать let! для принудительного вызова метода перед каждым примером.

Если вы хотите, чтобы что-то сохранялось во всех примерах, вы можете использовать перед хуком...before(:context) звучит так, как будто это то, что вам нужно. Возможно, вы сможете настроить вспомогательный метод, который запоминает в блоке before, чтобы избежать необходимости везде использовать переменную экземпляра (согласно этот комментарий):

def student
  @student ||= create(:student_with_profile_and_identity)
end

before(:context) do
  student # force student creation
end
05.09.2017
Новые материалы

Коллекции публикаций по глубокому обучению
Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

Представляем: Pepita
Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

Советы по коду Laravel #2
1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

3 способа решить квадратное уравнение (3-й мой любимый) -
1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

Создание VR-миров с A-Frame
Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

Демистификация рекурсии
КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..