NoMethodError: undefined method `run_list_for' when testing role with ChefSpec
Asked Answered
K

1

7

I'm trying to test a role with ChefSpec. I would rather not use Chef Zero (by requiring 'chefspec/server') just because it runs a bit slower than ChefSpec does on it's own.

Perhaps I'm reading the documentation wrong, but it doesn't look like Chef Zero is required to test a role. I haven't had any luck with my current configuration, however. This is my test:

require 'chefspec'

RSpec.configure do |config|
  config.cookbook_path = 'C:\projects\chef\cookbooks'
  config.role_path = 'C:\projects\chef\roles'
  config.log_level = :debug
  config.platform = 'ubuntu'
  config.version = '12.04'
end

describe 'my_cookbook::default' do
  let(:chef_run) do
    ChefSpec::Runner.new.converge('role[my_role]')
  end

  it 'runs without failing' do
    expect(chef_run)
  end
end

The role (located at roles/my_role.json):

{
    "name": "my_role",
    "description": "My role",
    "default_attributes": {
    },
    "run_list": [
        "recipe[my_cookbook::default]"
    ]
}

When I run the test, I receive:

NoMethodError: undefined method `run_list_for' for #<Hash:0x4fa3280>
./spec/role_spec.rb:13:in `block (2 levels) in <top (required)>'
./spec/role_spec.rb:17:in `block (2 levels) in <top (required)>'

If I modify my test to manually load the role into Chef Zero by requiring chefspec/server, that seems to work. I don't think I should have to mock the server from the way the documentation is written, but I could be wrong.

Am I doing something wrong? Is this a bug? Or do I have to use Chef Zero?

Kiushu answered 29/1, 2014 at 20:45 Comment(10)
The method run_list_for does not appear in ChefSpec or Chef Zero. Can I see your method?Lightproof
run_list_for (if that's what your referring to) is not my own method, it seems to be related to chef. The stack trace is generated on the expect(chef_run) line, and the default recipe itself is empty. The only references I could find are some posts related to old versions chef solo (version 10) that spewed out this same exception when the JSON didn't contain specific attribute values (like "json_class": "Chef::Role"). I added the JSON content, let me know if there's anything else I can post that may be helpful.Kiushu
What version of ChefSpec?Lightproof
What line is line #26 in spec/role_spec.rb? The one the error refers to?Catamite
What happens if you add "json_class":"Chef::Role" to your role?Lightproof
@DracoAter - Sorry for the confusion, I've updated the original post to reflect the correct line numbers. I must have copied that before making some alterations to the code.Kiushu
@Lightproof - Well that seems to fix it, should that be added to the ChefSpec documentation? One thing I now realize is that the docs show the role as a Ruby file as opposed to a JSON file - does that matter?Kiushu
On disk, Chef roles can be described as .rb or .json files - it's really your preference which you use, though each has its own syntax. Chef server has its own representation and you can translate reasonably easily with knife utility methods. If you are using a Chef server and you use knife to create a role or create the role on the server directly, you don't automatically get a file on disk for that role. You have to knife role list with a -f format flag, then save that output to your /roles directory.Interval
I am not certain what happens if you have a role specified in both .rb and .json files. It is recommended that you stick to one format for consistency and do not duplicate roles or re-use role names between the two formats.Interval
@Kiushu no, this isn't a ChefSpec issue, it's a Chef issue/misunderstanding.Lightproof
L
16

If you are using JSON roles, you must include the json_class:

"json_class": "Chef::Role"

If you are using Ruby roles, you don't need to do that.

Lightproof answered 1/2, 2014 at 18:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.