debow
debow

Reputation: 73

undefined local variable in chefspec on method included from gem

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

Answers (3)

debow
debow

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

Draco Ater
Draco Ater

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

Mr.
Mr.

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

Related Questions