Reputation: 73
I'm including a custom gem in a chef cookbook. No matter what I've tried I'm get similar errors to undefined local variable or method `host'
I've tried many different variations to this.
allow(HostOpsCookbook).to receive(:host).with(:sonic.version).and_return('10.0')
Gem layout
cust_gem
\lib
\ibus
\host
sonic.rb
host.rb
host.rb
module Ibus
class Host
attr_reader :sonic
def initialize
extend_type
end
def enxtend_type
@sonic = Ibus::Host::Sonic.new
end
end
end
host\sonic.rb
module Ibus
class Host
class Sonic
def version
.....
end
end
end
end
Chef cookbook
cookbook
\libraries
host_helper.rb
\recipes
default.rb
chef\cookbook\libraries\host_helper.rb
module HostOpsCookbook
def host
require_ibus_gem #Loads the gem
@@host ||= Ibus::Host.new
end
end
Chef::Recipe.send(:include, HostOpsCookbook) if defined?(Chef::Recipe)
Chef::Resource.send(:include, HostOpsCookbook) if defined?(Chef::Resource)
Chef::Provider.send(:include, HostOpsCookbook) if defined?(Chef::Provider)
chef\cookbook\recipes\default.rb
sonic_version = host.sonic.version
This as code works the call to the gem method works.
However I can't figure out how to stub the below in the spec tests.
host.sonic.version
Upvotes: 1
Views: 429
Reputation: 73
The below code it was ended up working. The version method was nested under the Host/Module, Sonic/Class which is extend when the host object is initialized. This is all shown above.
allow_any_instance_of(HostOpsCookbook).to receive_message_chain(:host, :sonic, :version).and_return('10.0')
Upvotes: 1
Reputation: 21206
allow(HostOpsCookbook).to
Is for stubbing class methods. You actually have a instance method, so you must use:
allow_any_instance_of(<Class>).to
Your host method is defined in module, you cannot create an instance from modules. So you must stub the instance of the Chef::Recipe object, as you call host method from recipe.
allow_any_instance_of(Chef::Recipe).to
Another problem would be stubbing sonic.version. As you try to chain stubbing, you must use rspec doubles in this case.
So the final result should be:
sonic_double = double("Sonic Double", version: "10.0")
allow_any_instance_of(Chef::Recipe).to receive(:host).and_return(sonic_double)
Upvotes: 0
Reputation: 10102
You need to install the required rubygem into the environment ChefSpec is running in.
This will make sure that the rubygem is resolved by ChefSpec.
Upvotes: 0