Search code examples
rubyunit-testingrspecpuppetrspec-puppet

How to rspec test a Puppet class when a parameter needs a resource reference


This may be a simple matter of mocking a resource, but...

class myclass (
  String stringParam,
  Integer intParam,
  File fileParam
) {
 # do some things
 $path = fileParam['title']
 $mode = fileParam['mode']
 # do some more things
 }

Now I want to write an rspec-puppet test for this class. How do I either create or mock a File resource and get it into the catalog that rspec-puppet uses, so that I can reference it?

The answers to this and this got me partway there, but everything I've tried has led to myClass complaining that it's being passed a string instead of a file reference.

...
let(:params) {{
  :stringParam => 'Here is my string',
  :intParam    => 238,
  :fileParam   => *??????,*
}}

Solution

  • There isn't really much support in rspec-puppet for this, as a class test parameters list is generated from the :params assuming only strings (or nested hashes/arrays etc. containing strings) or a couple of permitted symbol values used almost literally, :undef and :default. It doesn't have a way of passing in resource references.

    A workaround exists that lets you put literal content into a manifest though, by passing an object that responds to the inspect method. For example, in your spec_helper.rb:

    class ResourceReference
      def initialize(ref)
        @ref = ref
      end
    
      def inspect
        @ref
      end
    end
    

    And then in your spec:

    let(:params) {{
      :stringParam => 'Here is my string',
      :intParam    => 238,
      :fileParam   => ResourceReference.new("File[/etc/foo]"),
    }}
    

    rspec-puppet will call the inspect method on the ResourceReference object which returns the string you've passed in. This should be placed in the manifest unchanged.

    (This was originally used as a workaround for undef, which can now be passed as :undef.)

    As an aside, you can set let(:pre_condition) { "..." } to add literal content to the test manifest before the generated class { ... }, but I don't think there's a way to use that here.

    I'd strongly recommend filing a feature request against rspec-puppet.