代码之家  ›  专栏  ›  技术社区  ›  David Geismar

如何在使用rspec测试类中的任何方法之前初始化常规上下文变量

  •  0
  • David Geismar  · 技术社区  · 6 年前

    我是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中测试不同的方法,我希望在每个方法中修改以前在my before中创建的变量:每个块)。 例如:

      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>
    

    我意识到了我的过去:每个代码都是不输入的。实现这一点的好方法是,在测试类中的任何方法之前初始化一组实例变量的常规上下文。

    2 回复  |  直到 6 年前
        1
  •  0
  •   jdno    6 年前

    let 声明 before let(:foo) { block } foo 被调用。但是通过将语句包装在

    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
    

    现在,要修改对象,请使用 在上下文中阻塞。确保你没有混合 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
    

    这应该能解决你的问题。

        2
  •  0
  •   Onur Kucukkece    6 年前

    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!

    希望有帮助