使用rvm的ChefSpec测试包括

时间:2014-08-13 17:25:29

标签: rvm chef chefspec

所以我试图为我的一个厨师食谱编写一个单元测试(通过ChefSpec),但我得到一些奇怪的行为。

我的问题是包含rvm :: system_install配方,显然这会导致ChefSpec出现问题:

Failures:

1) theoracle::prereqs installs libyaml libyaml-devel sqlite-devel
 Failure/Error: let(:chef_run) { ChefSpec::Runner.new.converge('theoracle::prereqs')}
 NoMethodError:
   undefined method `each' for nil:NilClass
 # /Users/jdoe/workspace/cookbooks/rvm/libraries/chef_rvm_recipe_helpers.rb:44:in `install_pkg_prereqs'
 # /Users/jdoe/workspace/cookbooks/rvm/recipes/system_install.rb:29:in `from_file'
 # ./recipes/prereqs.rb:22:in `from_file'
 # ./spec/unit/recipes/prereqs_spec.rb:6:in `block (2 levels) in <top (required)>'
 # ./spec/unit/recipes/prereqs_spec.rb:15:in `block (2 levels) in <top (required)>'

违规代码段:

/Users/jdoe/workspace/cookbooks/rvm/libraries/chef_rvm_recipe_helpers.rb:

41:        def install_pkg_prereqs(install_now = node.recipe?("rvm::gem_package"))
42:          return if mac_with_no_homebrew
43:
44>>         node[:rvm][:install_pkgs].each do |pkg|
45:            p = package pkg do

这就是我的测试结果:

require 'spec_helper'
describe 'theoracle::prereqs' do
  let(:chef_run) { ChefSpec::Runner.new.converge('theoracle::prereqs')}

  it 'installs libyaml libyaml-devel sqlite-devel' do
    %W( libyaml libyaml-devel sqlite-devel ).each do |pkg|
      expect(chef_run).to_install_package(pkg)
    end
  end
end

这是theoracle::prereqs食谱(部分内容):

%W( libyaml libyaml-devel sqlite-devel ).each do |pkg|
  package pkg do
    action :install
  end
end

include_recipe 'rvm::system_install'

1 个答案:

答案 0 :(得分:1)

以下是发生的事情:

node[:rvm][:install_pkgs]

正在返回nil。因此,您正在调用nil.each并获取异常。不幸的是,为什么该属性可能是nil

有很多可能性

依赖

theoracle食谱中,您是否已在rvm添加了对metadata.rb食谱的依赖?

depends 'rvm'

如果没有这一行,Chef将不会加载RVM cookbook(因此不会加载其属性),导致install_pkgs属性为nil

默认属性(最有可能)

如果您在chef-rvm食谱中look at the code for determining the value of that attribute,则可以看到node[:rvm][:install_pkgs]仅在以下条件下设置:

case platform
when "redhat","centos","fedora","scientific","amazon"
  node.set['rvm']['install_pkgs']   = %w{sed grep tar gzip bzip2 bash curl git}
  default['rvm']['user_home_root']  = '/home'
when "debian","ubuntu","suse"
  node.set['rvm']['install_pkgs']   = %w{sed grep tar gzip bzip2 bash curl git-core}
  default['rvm']['user_home_root']  = '/home'
when "gentoo"
  node.set['rvm']['install_pkgs']   = %w{git}
  default['rvm']['user_home_root']  = '/home'
when "mac_os_x", "mac_os_x_server"
  node.set['rvm']['install_pkgs']   = %w{git}
  default['rvm']['user_home_root']  = '/Users'
end

对于ChefSpec,所有Ohai数据(设置platform键的内容)都被模拟为允许控制此行为。 最有可能,ChefSpec将其平台报告为chefspec,由于case语句没有默认块,因此该属性为nil

要解决此问题,请告诉ChefSpec表现得像某个特定操作系统:

ChefSpec::Runner.new(platform: 'ubuntu', version: '12.04')

或者在测试中手动设置属性:

let(:chef_run) do
  ChefSpec::Runner.new do |node|
    node.set['rvm']['install_pkgs'] = %w(whatever)
  end.converge(described_recipe)
end