I'm getting started writing tests for my Chef cookbooks. I'm using ChefSpec to unit test my cookbooks. I need to install a Chef Server on one of my hosts and I would like to write a test for that. So far I have:

A ChefSpec test file in spec/default_spec.rb:

require 'chefspec'  
require 'chefspec/berkshelf'

describe 'my_chef_server::default' do
  let(:chef_run) { ChefSpec::Runner.new.converge(described_recipe) }

  it 'includes the chef-server recipe' do
    expect(chef_run).to include_recipe('chef-server')

A metadata.rb file which declares that the chef-server cookbook is a dependency.

depends 'chef-server'

A recipes/default.rb which includes the chef-server recipe:

include_recipe 'chef-server'

When I run my tests (using rspec) I get an error:

Recipe Compile Error in /var/folders/5g/dq2jk1sn30dgf7p4qhbvcjq80000gn/T/d20140429-77773-nxjusi/cookbooks/my_chef_server/recipes/default.rb

Could not locate chef-server package matching version 'latest' for node.

Cookbook Trace:
  /var/folders/5g/dq2jk1sn30dgf7p4qhbvcjq80000gn/T/d20140429-77773-nxjusi/cookbooks/chef-server/recipes/default.rb:31:in `from_file'
  /var/folders/5g/dq2jk1sn30dgf7p4qhbvcjq80000gn/T/d20140429-77773-nxjusi/cookbooks/my_chef_server/recipes/default.rb:11:in `from_file'

Relevant File Content:

 24:      node['chef-server']['nightlies']
 25:      )
 26:    unless omnibus_package
 27:      err_msg = 'Could not locate chef-server'
 28:      err_msg << ' pre-release' if node['chef-server']['prereleases']
 29:      err_msg << ' nightly' if node['chef-server']['nightlies']
 30:      err_msg << " package matching version '#{node['chef-server']['version']}' for node."
 31>>     fail err_msg
 32:    end
 33:  else
 34:    omnibus_package = node['chef-server']['package_file']
 35:  end
 37:  package_name = ::File.basename(omnibus_package)
 38:  package_local_path = "#{Chef::Config[:file_cache_path]}/#{package_name}"
 40:  # Ensure :file_cache_path exists



  1) my_chef_server::default includes the chef-server recipe
     Failure/Error: let(:chef_run) { ChefSpec::Runner.new.converge(described_recipe) }
       Could not locate chef-server package matching version 'latest' for node.
     # /var/folders/5g/dq2jk1sn30dgf7p4qhbvcjq80000gn/T/d20140429-77773-nxjusi/cookbooks/chef-server/recipes/default.rb:31:in `from_file'
     # /var/folders/5g/dq2jk1sn30dgf7p4qhbvcjq80000gn/T/d20140429-77773-nxjusi/cookbooks/my_chef_server/recipes/default.rb:11:in `from_file'
     # ./spec/default_spec.rb:6:in `block (2 levels) in <top (required)>'
     # ./spec/default_spec.rb:9:in `block (2 levels) in <top (required)>'

Finished in 0.28717 seconds
2 examples, 1 failure

Failed examples:

rspec ./spec/default_spec.rb:8 # my_chef_server::default includes the chef-server recipe

As far as I can tell, ChefSpec is correctly loading and executing my cookbook and running the dependent chef-server cookbook. However, the error shows that the chef-server cookbook is not able to install the latest chef-server package.

How should I write or mock my test so that I can correctly test that Chef Server is installed successfully?

| improve this question | | | | |
  • It looks as though in order to avoid this exception during the chef-spec run you will need to mock out the OmnitruckClient class before calling converge on the runner. – punkle May 14 '14 at 12:09

So this is largely due to a new instance of a class named OmnitruckClient being created in the chef-server default recipe. The OmnitruckClient is basically an HTTP call to the Omnitruck endpoint which is meant to return a URL where the chef-server recipe will then download the package from.

There's a couple of ways handling the testing of this behavior that I can think of.

Since the native ChefSpec virtual 'platform' is named chefsepc, the Omnitruck service will never respond with a correct URL link, so one method would be to supply a platform and version to the Spec test, which may have other values later on.

You can supply these selections in either the general configuration for RSpec, or per-test case (or even each converge).

I find it simplest to set these in the spec_helper.rb file. See here for more on the configuration options.

Another mode may be to try mocking/stubbing out the OmnitruckClient class (or the Net::HTTP.get method it uses), but it seemed like this might be a little more confusing, and I couldn't actually get that to work yet.

| improve this answer | | | | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.