Как инициализировать переменные общего контекста перед тестированием любых методов в классе с помощью rspec - PullRequest
0 голосов
/ 12 июня 2018

Я новичок в rspec.Я пишу тест для класса обслуживания и хотел бы, чтобы несколько экземпляров были инициализированы до того, как я выполню какой-либо из блока описаний.Я делаю что-то вроде:

RSpec.describe MyService do
before :each do

    let(:product){create(:product)}
    let(:article_student){ create(:article, targets: [:student], vat_type: vat_type, product: product)} #target student
    let(:article_teacher){ create(:article, targets: [:teacher], vat_type: vat_type, product: product) }#target teacher
    # creer des offres
    let(:offer){create(:offer, target: :student, license_length: :m12)}
    let(:offer_special_cyclic){create(:offer_special, cyclic_amount: true, free_article_id: article_teacher.id, minimum_amount: 10, license_length: :m12)} # free article @article_teacher
    let(:offer_special_non_cyclic){create(:offer_special, cyclic_amount: false, free_article_id: article_teacher.id, minimum_amount: 10, license_length: :m12)} # free article @article_teacher
    let(:order){ create(:order, establishment_account: establis

hment_account)}
end

, тогда у меня будет несколько блоков описаний (для тестирования различных методов в MyService, и я бы хотел в каждом из них изменить ранее созданные переменные в моем блоке before: each.экземпляр:

  describe "#create_from_order" do
    subject{ licenses }
    context "first time worker runs" do
      order.already_went_through_license_worker = false
      order.save!
      LicenseService.new.create_from_order(@order.id)
      let(:licenses){ License.where(order_id: @order.id)}
      specify { subject.count.to eq 34 }
      specify { subject.pluck(:is_from_offer_special).count(true).to eq 4}
      specify { subject.pluck(:is_from_offer_special).count(false).to eq 30 }
end
end

Однако, когда я пытаюсь запустить свой тест, я получаю, что order внутри моего блока context не определен ...

undefined local variable or method `order' for #<Class:0x007fc689ddfdb8>

Я понимаю, что мойbefore: каждый код никогда не вводится. Какой хороший способ добиться этого, это инициализировать кучу общего контекста переменной экземпляра перед тестированием любых методов в классе.

Ответы [ 2 ]

0 голосов
/ 12 июня 2018

Сначала переместите ваши операторы let из блока before.let вычисляется лениво, что означает, что определенные вами блоки (let(:foo) { block }) выполняются только при вызове foo.Но, помещая операторы в блок before, вы фактически не вызываете их, поэтому ничего не произойдет.

Чтобы выполнить операторы перед каждым тестом, используйте let!.Это не лениво оценивается, и выполняется, как только вы определите инструкцию, что вам и нужно в этом случае.

RSpec.describe MyService do
  let!(:product){create(:product)}
  let!(:article_student){ create(:article, targets: [:student], vat_type: vat_type, product: product)} #target student
  let!(:article_teacher){ create(:article, targets: [:teacher], vat_type: vat_type, product: product) } #target teacher
  # creer des offres
  let!(:offer){create(:offer, target: :student, license_length: :m12)}
  let!(:offer_special_cyclic){create(:offer_special, cyclic_amount: true, free_article_id: article_teacher.id, minimum_amount: 10, license_length: :m12)} # free article @article_teacher
  let!(:offer_special_non_cyclic){create(:offer_special, cyclic_amount: false, free_article_id: article_teacher.id, minimum_amount: 10, license_length: :m12)} # free article @article_teacher
  let!(:order){ create(:order, establishment_account: establishment_account)}
end

Теперь, чтобы изменить объекты, используйте блок before внутриконтекст.И убедитесь, что вы не смешиваете order и @order.

context "first time worker runs" do
  before do
    order.already_went_through_license_worker = false
    order.save!
    LicenseService.new.create_from_order(order.id)
  end

  let(:licenses){ License.where(order_id: order.id)}

  specify { subject.count.to eq 34 }
  specify { subject.pluck(:is_from_offer_special).count(true).to eq 4}
  specify { subject.pluck(:is_from_offer_special).count(false).to eq 30 }
end

Это должно решить вашу проблему.

0 голосов
/ 12 июня 2018

Попробуйте следующим образом

RSpec.describe MyService do
  describe "#create_from_order" do
    let(:product){create(:product)}
    let(:article_student){ create(:article, targets: [:student], vat_type: vat_type, product: product)} #target student
    let(:article_teacher){ create(:article, targets: [:teacher], vat_type: vat_type, product: product) }#target teacher
    # creer des offres
    let(:offer){create(:offer, target: :student, license_length: :m12)}
    let(:offer_special_cyclic){create(:offer_special, cyclic_amount: true, free_article_id: article_teacher.id, minimum_amount: 10, license_length: :m12)} # free article @article_teacher
    let(:offer_special_non_cyclic){create(:offer_special, cyclic_amount: false, free_article_id: article_teacher.id, minimum_amount: 10, license_length: :m12)} # free article @article_teacher
    let(:order){ create(:order, establishment_account: establishment_account)}

    context "first time worker runs" do
      order.already_went_through_license_worker = false
      order.save!
      LicenseService.new.create_from_order(@order.id)
      let(:licenses){ License.where(order_id: @order.id)}
      specify { subject.count.to eq 34 }
      specify { subject.pluck(:is_from_offer_special).count(true).to eq 4}
      specify { subject.pluck(:is_from_offer_special).count(false).to eq 30 }
    end
  end
end

Также метод let запускается, если вызываются только объекты.Если вы хотите, чтобы он запускался несмотря ни на что, вы должны использовать метод let!.

Надеюсь, это поможет

...