Mocking Citadel class in Chefspec?

ohai guys!

i’m running into some confusion with how to mock out this class from the citadel cookbook using chefspec.

At the moment, I’m trying to do something like below but I’m running into a uninitialized constant error.

I also noticed somebody here also has a similar issue. perhaps @coderanger could shed some light on this. Thanks!

let(:chef_run) { ChefSpec::SoloRunner.converge(described_recipe) }
before do
  Citadel.stub(:new) { puts 'im mocking citadel' }`
end

I think the uninitialized constant will show if you haven’t required the code that creates the Citadel class in your spec’s load path (either top of the file or via spec_helper).

As to stubbing, here’s a thread on chefsepc repo that explains a bit more, and here’s a link to rspec’s mocks docs that is always useful information to have.

1 Like

cool, thanks for the info on that @Mike! I was able to get it working!

Also, from what was explained here, I had to add the unless to my class to prevent the chefspec converge from overriding my stub.

spec_helper.rb

require 'chefspec'
require 'chefspec/berkshelf'
require_relative 'libraries/citadel.rb'
at_exit { ChefSpec::Coverage.report! }

citadel.rb

unless defined?(Citadel)
  class Citadel
    def initialize
      puts 'im mocking citadel'
    end
  end
end

default_spec.rb

require 'spec_helper'
describe 'mycookbook::default' do
  let(:chef_run) { ChefSpec::SoloRunner.converge(described_recipe) }
  before do
    allow(Citadel).to receive(:new).and_return("supersecret")
  end
  it 'creates ssh key' do
    expect(chef_run).to create_file('/home/ubuntu/.ssh/dios.pem').with(mode: '600')
  end
end

also, for clarity sake, this is what the recipe looks like.

default.rb

file '/home/ubuntu/.ssh/dios.pem' do
  content citadel["#{cookbook_name}/dios.pem"]
  mode '600'
  action :create
end