Rspec-rails: Is there a way to stub Rails credential key?

Created on 14 Mar 2019  路  11Comments  路  Source: rspec/rspec-rails

Similar to stubbing environment variable, can we stub Rails credential key?

What Ruby, Rails and RSpec versions are you using?

Ruby version: 2.6.1
Rails version: 5.2.2
Rspec version: 3.8

Observed behaviour

allow(Rails.application.credentials).to receive(:my_token).and_return('')

Expected behaviour

allow(Rails.application.credentials).to receive(:my_token).and_return('123')
Rails.application.credentials.my_token
=> '123'

All 11 comments

As credentials is an object you have to stub what you wish to retrieve. So:

allow(Rails.application.credentials).to receive(:my_token).and_return('123')
Rails.application.credentials.my_token
# => 123

allow(Rails.application.credentials).to receive(:[]).with(:my_token).and_return('345')
Rails.application.credentials[:my_token]
# => 345

It'd be better to use it as designed and setup a test environment set of credentials.

Thanks @JonRowe I edited the post to actually focus on the issue (described in your first example).

my_token is already defined in credentials.yml.enc but I need to override the value in my specs.

I tried indeed the following but it keeps the value defined in credentials.yml.enc.

allow(Rails.application.credentials).to receive(:my_token).and_return('123')
Rails.application.credentials.my_token
# => value_from_credentials_file

I just did a test on a fresh_app

And I had no issue.

My credentials file looks like this:

 aws:
  access_key_id: 123
  secret_access_key: 345
olimart: 'from_config'

# Used as the base secret for all MessageVerifiers in Rails, including the one protecting cookies.
secret_key_base: xxxx
require 'rails_helper'

describe 'Credentials' do
  it 'stubs credentials' do
    allow(Rails.application.credentials).to receive(:olimart).and_return('123')
    expect(Rails.application.credentials.olimart).to eq('123')
  end
end

no issues.

@benoittgt What's your master key?

Amazing. The exact same code fails on my end. I appreciate your help.

@benoittgt I'll leave it up to you to decide if this should be reopened :)

I'll leave it up to you to decide if this should be reopened :)

don't think so. Just need to find out why but in the meantime we came up with a workaround.

Actually, I have the exact same issue, and I cannot figure out why, @olimart, what is the workaround you implemented ?

@Uelb

shared_context 'encrypted configuration' do
  def stub_credential(key, value)
    allow(Rails.application).to receive(:credentials).and_return(OpenStruct.new(key.to_sym => value))
  end
end

# usage
stub_credential(:my_credential, 123)

what is the usage for a deeper structure, for example if the credentials.yml file has

test:
level:
MY_DEEP_ENV_VAR: 12345

(sorry, the above should be indented as per a .yml file

would you suggest:
stub_credential([:test][:level][:MY_DEEP_ENV_VAR], 67890) ??

  allow(Rails.application).to receive_message_chain(:test, :level, :MY_DEEP_ENV_VAR => 67890)

Rubocop was complaining about receive_message_chain, so I think I'm going to go with

allow(Rails.application).to receive(:credentials).and_return(JSON.parse({ checkr: { secret: 'super duper secret' } }.to_json, object_class: OpenStruct))
Was this page helpful?
0 / 5 - 0 ratings