Unit testing modifications to the CHEF resource collection


#1

Ohai Chefs!

I am having an issue creating a unit test for a recipe that includes a modification to the resource collection. I am modifying the resource collection so that the template from my wrapper cookbook overrides the template in the community SQL Server cookbook.

The error I receive when I run the unit test is …

“Cannot find a resource matching template[ConfigurationFile.ini.erb] (did you define it first?)”

My guess is that, for testing purposes, I need to mock the template resource. How do I do this?

Recipe Code

include_recipe 'sql_server::server'  # Install SQL Server
…
resources('template[ConfigurationFile.ini.erb]').cookbook 'os_install_sql'

Test Code

require 'spec_helper'

describe 'os_install_sql::install_sql' do
  context 'When all attributes are default, on an unspecified platform' do
    let(:chef_run) do
      ChefSpec::ServerRunner.new do |_node, server|
        server.create_data_bag(
          'sql_servers',
            'db001' => {
              'domain_fqdn' => 'kitchen.local',
              'safe_mode_pass' => '******'
            }
        )
      end.converge(described_recipe)
    end

    before(:each) do
      allow_any_instance_of(Chef::Recipe).to receive(:include_recipe).and_call_original
      allow_any_instance_of(Chef::Recipe).to receive(:include_recipe).with('sql_server::server')
    end

    it 'Expects include_recipe sql_server::server' do
      expect_any_instance_of(Chef::Recipe).to receive(:include_recipe).with('sql_server::server')
      chef_run
    end

    it 'Converges successfully' do
      expect { chef_run }.to_not raise_error
    end
  end
end

#2

You’re code is false at first, the unit test has nothing to do here, it’s just the recipe compilation which can’t find a resource template[ConfigurationFile.ini.erb] as it don’t exist, the format if resource[name_of_resource] so in your specific case should be template[/path/to/target/file] and so it should not be the source template file (which is searched in the cookbook property, here you’re right on the how to modify it)

As you don’t show the included recipe code involved for this template, I can’t be more precise on what the proper syntax should be at end.


#3

Hi!
Thanks for your response. At the moment I want to test that the sql_server::server recipe is included. I don’t want to test the template resource; I simply want to stop the test fail because it can’t find the template resource.
I’ve included below the section of code from the included recipe. This code works and the template from the wrapper cookbook is used correctly.

config_file_path = win_friendly_path(File.join(Chef::Config[:file_cache_path], 'ConfigurationFile.ini'))

if node['sql_server']['sysadmins'].is_a? Array
  sql_sys_admin_list = node['sql_server']['sysadmins'].join(' ')
else
  sql_sys_admin_list = node['sql_server']['sysadmins']
end

template 'ConfigurationFile.ini.erb' do
  source 'ConfigurationFile.ini.erb'
  path config_file_path
  variables(
    sqlSysAdminList: sql_sys_admin_list
  )
end

#4

Here I’m lost, there’s no reason it hangs unless chefspec use a different version for the sql_server cookbook.

The error message by itself if a chef compilation phase error, saying it can’t find the resource. I suspect your second allow_any_instance in before block to stop it from loading the recipe, and thus the resource is not created.

You should get rid of it (or explain why you don’t want it to be loaded).
If the matter is seeing the sql_server::server resources in the coverage report, you can ignore them by adding a filter to the coverage report block, as show here

Sorry I misread your question and go to the wrong conclusion at first glance :slight_smile:


#5

Are you using the berks plug-in so that the cookbook dependencies are
loaded in Chefspec?

If so then you can write a test that states:

expect(chef_run).to include_recipe(‘sql_server::server’)

and it will load the resources from that recipe for your test, which means
the template will be found

If you are actually attempting to keep the resources from being loaded in
your unit test (which can be useful as it can do annoying things to your
coverage reports, but it also can cause difficult hurdles) you’ll probably
have to mock/stub the template when setting up your runner somehow. I’ve
honestly never had to stub an actual Chef resource in ChefSpec and I can’t
find any examples from a quick google, but I’m sure someone more
knowledgeable than I on this list can help you with that.