代码之家  ›  专栏  ›  技术社区  ›  Karol Selak

如何使用冗余的'let!`方法调用?

  •  0
  • Karol Selak  · 技术社区  · 6 年前

    我如何在我的Rails应用程序中使用RSpec测试块:

    describe "POST create" do
      describe "if we have a logged in user and he can be an owner" do
        describe "and if params are valid" do
          let!(:service_attributes_with_categories_1_and_2) {
            FactoryBot.attributes_for :service_with_categories_1_and_2
          }
          let!(:category_1) { FactoryBot.create :category, {id: 1} }
          let!(:category_2) { FactoryBot.create :category, {id: 2} }
    
          it "creates a new service" do
            # ...
          end
          it "creates associations with categories" do
            # ...
          end
        end
        describe "and if categories are not valid" do
          # ...
        end
        describe "and if some common service params are not valid" do
          # ...
        end
      end
      describe "if no user is logged in, but params are valid" do
        let!(:service_attributes_with_categories_1_and_2) {
          FactoryBot.attributes_for :service_with_categories_1_and_2
        }
        let!(:category_1) { FactoryBot.create :category, {id: 1} }
        let!(:category_2) { FactoryBot.create :category, {id: 2} }
        it "doesn't create a new service" do
          # ...
        end
        it "doesn't create associations with categories" do
          # ...
        end
      end
      describe "if logged user cannot be an owner, but params are valid" do
        let!(:service_attributes_with_categories_1_and_2) {
          FactoryBot.attributes_for :service_with_categories_1_and_2
        }
        let!(:category_1) { FactoryBot.create :category, {id: 1} }
        let!(:category_2) { FactoryBot.create :category, {id: 2} }
    
        it "doesn't create a new service" do
          # ...
        end
        it "doesn't create associations with categories" do
          # ...
        end
      end
    end
    

    正如我们所看到的,我有很多多余的 let! 方法调用,但我不知道如何才能使其干燥。我不能只定义普通方法,因为在这种情况下,变量只在该方法的作用域中可用。我也不能让我的类别在一般范围内创建,因为在两种情况下,由于测试的性质,它们不应该被创建。那么,从技术上讲,我应该如何做到这一点?

    2 回复  |  直到 6 年前
        1
  •  1
  •   Karol Selak    6 年前

    您可以按以下方式干燥规格:

    1) 使用 let 而不是定义方法。

    2) 安排您的 context 以便于容纳更多案例的方式进行阻塞。

    describe 'POST create' do
      let!(:service_attributes_with_categories_1_and_2) {
        FactoryBot.attributes_for :service_with_categories_1_and_2
      }
      let!(:category_1) { FactoryBot.build :category, {id: 1} }
      let!(:category_2) { FactoryBot.build :category, {id: 2} }
      let(:save_categories_1_and_2) { category_1.save && category_2.save }
    
      context 'when user is logged in' do
        context 'when user is an owner' do
          context 'when params are valid' do
            before do
              save_categories_1_and_2
            end
    
            it 'creates a new service' do
            end
    
            it 'creates associations with categories' do
            end
          end
    
          context 'when categories are not valid' do
          end
    
          context 'when some common service params are not valid' do
          end
        end
    
        context 'when user is not an owner' do
          context 'when params are valid' do
            before do
              save_categories_1_and_2
            end
    
            it "doesn't create a new service" do
            end
    
            it "doesn't create associations with categories" do
            end
          end
        end
      end
    
      context 'when no user is logged in' do
        context 'when params are valid' do
          before do
            save_categories_1_and_2
          end
    
          it "doesn't create a new service" do
          end
    
          it "doesn't create associations with categories" do
          end
        end
      end
    end
    
        2
  •  0
  •   Karol Selak    6 年前

    最后我决定把 FactoryBot.create 功能分为两步: FactoryBot.build .save 函数在获取的对象上运行。它允许我移动 let! 调用main作用域和define方法,在需要的情况下,该方法会准确地保存构建的对象。我的干代码现在看起来是这样的:

    describe "POST create" do
      let!(:service_attributes_with_categories_1_and_2) {
        FactoryBot.attributes_for :service_with_categories_1_and_2
      }
      let!(:category_1) { FactoryBot.build :category, {id: 1} }
      let!(:category_2) { FactoryBot.build :category, {id: 2} }
    
      def save_categories_1_and_2
        category_1.save
        category_2.save
      end
    
      describe "if we have a logged in user and he can be an owner" do
        describe "and if params are valid" do
          before(:each) do
            save_categories_1_and_2
          end
          it "creates a new service" do
            # ...
          end
          it "creates associations with categories" do
            # ...
          end
        end
        describe "and if categories are not valid" do
          # ...
        end
        describe "and if some common service params are not valid" do
          # ...
        end
      end
      describe "if no user is logged in, but params are valid" do
        before(:each) do
          save_categories_1_and_2
        end
        it "doesn't create a new service" do
          # ...
        end
        it "doesn't create associations with categories" do
          # ...
        end
      end
      describe "if logged user cannot be an owner, but params are valid" do
        before(:each) do
          save_categories_1_and_2
        end
        it "doesn't create a new service" do
          # ...
        end
        it "doesn't create associations with categories" do
          # ...
        end
      end
    end
    

    非常感谢@midlins和@Taryn East为我指明了正确的方向@Taryn East-您建议的调整也适用于此处描述的情况,但在我的应用程序中,我还有更高级的情况,这还不够。我认为这里提出的解决方案更具普遍性。