Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

how to unit test class with parameter of type Array[Type[CatalogEntry]] #715

Open
brettjacobson opened this issue Aug 16, 2018 · 1 comment

Comments

@brettjacobson
Copy link

I want to parameterize the notify parameter on an exec (to restart a service), and the code works "for real". But I cannot figure out the syntax to unit test the class.

Example project here: https://github.com/brettjacobson/puppet-demo

The failures are related to supplying a dummy resource in the :params block, usually Error while evaluating a Resource Statement, Class[Testdemo::Test1]: parameter 'notifications' index 0 expects a Type[CatalogEntry] value, got String

@rodjek
Copy link
Owner

rodjek commented Aug 17, 2018

Thanks for submitting this @brettjacobson, the main issue here is with my documentation so I'll leave this issue open until the docs are fixed, but here's a breakdown of the changes needed to get the tests in your sample module passing.


diff --git a/.fixtures.yml b/.fixtures.yml
index 2296adb..1c4c8f3 100644
--- a/.fixtures.yml
+++ b/.fixtures.yml
@@ -3,4 +3,4 @@
 ---
 fixtures:
   forge_modules:
-#     stdlib: "puppetlabs/stdlib"
+      powershell: "puppetlabs/powershell"

Not related to the error you're reporting, but the test manifest depends on the powershell module being in place.


diff --git a/spec/classes/test1_spec.rb b/spec/classes/test1_spec.rb
index 76d7e71..e3e0d32 100644
--- a/spec/classes/test1_spec.rb
+++ b/spec/classes/test1_spec.rb
@@ -7,7 +7,7 @@ describe 'testdemo::test1' do
       let(:pre_condition) { "service {'test2svc':}"}
       let(:params) do
         {
-          notifications: ["Service[test2svc]",]
+          notifications: [ref('Service', 'test2svc')]
         }
       end

This is the main thing that the current documentation is lacking. When preparing to run the tests, rspec-puppet has to take the various inputs from your spec file and convert it into a Puppet manifest and unfortunately it's rather difficult to programatically determine the intent behind the input strings (e.g. should "Service[test2svc]" be rendered as a string or as a reference?). For that reason, we default to assuming that things that look like strings are strings and your test manifest ended looking like this:

service { 'test2svc': }
class { 'testdemo::test1': notifications => ["Service[test2svc]"] }

To work around this (and this is the bit that isn't properly documented), there is a ref method that you can use when specifying your params to force rspec-puppet to render the value as a resource reference. The ref method takes two parameters: the resource type and the resource title/name. So with the change in the diff above, your test manifest ends up looking like this:

service { 'test2svc': }
class { 'testdemo::test1': notifications => [Service[test2svc]] }

diff --git a/spec/classes/test1_spec.rb b/spec/classes/test1_spec.rb
index e3e0d32..8d2f08f 100644
--- a/spec/classes/test1_spec.rb
+++ b/spec/classes/test1_spec.rb
@@ -12,7 +12,7 @@ describe 'testdemo::test1' do
       end
 
       it { is_expected.to compile }
-      it { is_expected.to contain_exec('sample-exec').with_notify("Service[test2svc]") }
+      it { is_expected.to contain_exec('sample-exec').that_notifies("Service[test2svc]") }
     end
   end
 end

While it is possible to test relationships using the with_* methods, it has a couple of downsides in that you must specify the exact relationships (so in this case, as you specified the type of this value as an array of catalogue entries it would have to be with_notify(["Service[test2svc]"])) and that it does not fully resolve the dependency graph (which is not a problem in this simple example).

The better solution is to use the special relationship matching methods which take care of the afore mentioned downsides for you automatically.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants