linuxwinapichef-infrachefspec

Chefspec Stubbing out Win32::Service on Linux


Our cookbook is used on both Linux and Windows machines, and when it runs/converges, the code runs perfectly on both types of systems. However the rake unit test fails on Linux. In my recipe I have:

service 'MyService' do
  action %i[enable start]
  only_if { ::Win32::Service.exists?("MyService") }
  not_if { ::File.exist?("#{install_dir}\\scripts\\instance-stopped") }
end

The error we are getting is:

Failures:

  1. perfagent::install_windows When set to install agent on Windows converges successfully Failure/Error: expect { chef_run }.to_not raise_error

    expected no Exception, got #<NameError: uninitialized constant Win32> with backtrace: # /tmp/chefspec20200924-2530-350e0zfile_cache_path/cookbooks/perfagent/resources/install_agent.rb:83:in `block (3 levels) in class_from_file'

Is it possible, for just Linux systems, to dummy out the value in my spec file for the "only_if" above so that my rake unit test succeeds whenever we run the rakes on Linux?


Update:

As the cookbook is executed on both Linux and Windows systems, we have a check early in the execution of the cookbook such as:

if node['platform_family'] == 'windows'
  include_recipe 'cookbook::install_windows'
elsif node['platform_family'] == 'rhel'
  include_recipe 'cookbook::install_linux'
else
  log "This OS family (#{node['platform_family']})  is not supported" do
    level :info
  end
end

This means that the cookbook only calls the relevant recipes depending on platform_family. However, when we run rake unit on Linux we get the above error and on Windows the rake succeeds.

I've tried adding:

allow(::Win32::Service).to receive(:exists?).with(windows_service[:name]).and_return(true)

to the spec file, but this still fails on Linux and causes the Windows rake unit to fail too.


Solution

  • In the case of nested classes the stubbing is a little bit more complex. You also need to stub the class itself. Use stub_const from the RSpec for that:

    let :subject do
      fake_win32 = Class.new
      stub_const('Win32::Service', fake_win32)
      allow(fake_win32).to receive(:exists?).and_return false
      ChefSpec::Runner.new(platform: 'windows', version: '2008R2').converge described_recipe
    end