ruby-on-railsrspecrspec-railsrspec-mocks

Rspec stubbing a constant set to a Rails credential


I have a class:

class Vendor::Connection
  VENDOR_CLIENT_ID = Rails.application.credentials.vendor_api[:client_id].freeze
  VENDOR_CLIENT_SECRET = Rails.application.credentials.vendor_api[:client_secret].freeze

  # ...

  def token_body
    {
      client_id: VENDOR_CLIENT_ID,
      client_secret: VENDOR_CLIENT_SECRET,
    }
  end
end

When I attempt to mock the credentials using any of the methods in this Rspec Github Issue

require 'rails_helper'

describe Vendor::Connection do
  before do
    allow(Rails.application.credentials).to receive(:vendor_api).and_return({ client_id: '123' })
  end

  it 'works' do
    expect(true).to eq(true)
  end
end

I receive:

Failure/Error: VENDOR_CLIENT_ID = Rails.application.credentials.vendor_api[:client_id]

NoMethodError:
  undefined method `[]' for nil:NilClass

I also tried a before block of:

  before do
    stub_const('Vendor::Connection::VENDOR_CLIENT_ID', '123')
    stub_const('Vendor::Connection::VENDOR_CLIENT_SECRET', '456')
    stub_const('Vendor::Connection::VENDOR_PARTNER_ID', '789')
  end

I still receive:

Failure/Error: VENDOR_CLIENT_ID = Rails.application.credentials.vendor_api[:client_id]

NoMethodError:
  undefined method `[]' for nil:NilClass

I tried:

shared_context 'credentials' do
  before do
    allow(Rails.application).to receive(:credentials).and_return(OpenStruct.new(vendor_api: {client_id: '123', client_secret: '456', partner_id: '789'}))
  end
end

describe Vendor::Connection do
  include_context 'credentials'

  it 'works' do
    expect(true).to eq(true)
  end
end

Which also returned:

Failure/Error: VENDOR_CLIENT_ID = Rails.application.credentials.vendor_api[:client_id]

NoMethodError:
  undefined method `[]' for nil:NilClass

I also attempted to put a binding.pry as the first line in the before block, but it fails before getting to the binding.pry

Running on: ruby 3.0.5 rails 6.1.7.4 rspec 3.10.0 rspec-rails 4.1.2

Any help would be greatly appreciated


Solution

  • I suggest to use different credentials for different environments and do not stub them

    rails credentials:edit --environment test
    

    The above command does the following:

    Since that credentials and key are for tests only, you can commit both files with Git and use them in CI if needed