Home > Blockchain >  Make rspec more DRY by accessing let variable in describe block
Make rspec more DRY by accessing let variable in describe block

Time:06-25

I'm trying to DRY up rspec tests that keeps on declaring let(:createBody) do...end. I thought to take out the let statement and just modify the variable on each block as needed. However the variable (createBody) is not accessible. Added a comment on sample code below to see exactly where I want to modify createBody.

post "Creates object", controller_action: :create do
  ...
  let(:createBody) do
    {
      name: "yes",
      type: "my_type",
      amount_cents: 200,
      parameters: {
        day: "today"
      },
      user_group_ids: [],
      user_ids: []
    }
  end

  # no users or groups
  response 201, "object created" do
    ...

    run_test! do |res|
      # this block works fine and can access createBody
      body = JSON.parse(res.body)
      expect(body["name"]).to eq(createBody[:name])
      expect(body["amount_cents"]).to eq(createBody[:amount_cents])
      expect(body["type"]).to eq(createBody[:type])
    end
  end

  # with users
  response 201, "autocharge rule created" do
    ...

    # want to make some modifications on createBody here, like adding user_ids, but it is out of scope
    
    run_test! do |res|
      # this block works fine and can access createBody
      body = JSON.parse(res.body)
      expect(body["user_ids"]).to match_array(createBody[:user_ids])
    end
  end
  ...
end

Is there a way to achieve this approach? Are there any alternatives?

CodePudding user response:

I assume response block works in the same way as context

post "Creates object", controller_action: :create do
  let(:createBody) do
    {
      name: "yes",
      type: "my_type",
      amount_cents: 200,
      parameters: {
        day: "today"
      },
      user_group_ids: [],
      user_ids: user_ids # now we can add a let(:user_ids) to each context
    }
  end

  response 201, "object created" do
    let(:user_ids) { [] } # empty since we're not using it here

    ...

    run_test! do |res|
      # this block works fine and can access createBody
      body = JSON.parse(res.body)
      expect(body["name"]).to eq(createBody[:name])
      expect(body["amount_cents"]).to eq(createBody[:amount_cents])
      expect(body["type"]).to eq(createBody[:type])
    end
  end

  # with users
  response 201, "autocharge rule created" do
    let(:user_ids) { [1, 2, 3] } # add required ids

    ...
    
    run_test! do |res|
      # this block works fine and can access createBody
      body = JSON.parse(res.body)
      expect(body["user_ids"]).to match_array(createBody[:user_ids]) # we can match by user_ids now
    end
  end
  ...
end
  • Related