繁体   English   中英

如何通过冗余的`let!`方法调用来干燥RSpec测试?

[英]How to DRY up RSpec tests with redundant `let!` method calling?

我如何使用RSpec在我的Rails应用程序中进行这样的测试:

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! 方法调用,但我不知道如何使其变干。 我不能只定义普通方法,因为在这种情况下,变量仅在此方法的范围内可用。 我也不能让我的类别在一般范围内创建,因为在两种情况下,由于测试的性质,不应创建类别。 那么,从技术上我该怎么做呢?

您可以按以下方式使您的规格变干:

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

最后,我决定将FactoryBot.create函数分为两个步骤: FactoryBot.build.save函数在获得的对象上运行。 它让我动容了let! 调用主作用域,并定义方法,在需要的情况下,此方法可以完全保存构建的对象。 我的DRY代码现在看起来像这样:

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-您建议的调整方式也适用于此处所述的情况,但是在我的应用中,我还拥有更高级的情况,这还不够。 我认为这里介绍的解决方案更具通用性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM