断言 Chef 运行 包含另一本食谱中的食谱

Assert that the Chef run included a recipe from another cookbook

$ cat Gemfile | grep "'chefspec'\|'chef'"
  gem 'chef', '12.8.1'
  gem 'chefspec', '4.6.1'

$ cat cookbooks/foo/recipes/default.rb | grep include
include_recipe 'bar'

$ cat cookbooks/foo/metafata.rb | grep depends
depends 'bar'

运行ning chefspecbar 食谱中的所有资源输出 Untouched Resources:。 我遵循 include recipe 断言,但它使用 allow_any_instance_of,这可能不是最佳做法。 我按如下方式使用它:

$ cat cookbook/foo/spec/recipes/default_spec.rb
describe 'foo::default' do
  cached(:chef_run) { ChefSpec::ServerRunner.converge(described_recipe) }
  let(:recipe) { instance_double(Chef::Recipe, cookbook_name: 'foo', recipe_name: 'default') }

  before do
    allow_any_instance_of(Chef::Recipe).to receive(:include_recipe).and_call_original
    allow_any_instance_of(recipe).to receive(:include_recipe).with('bar')
  end

  it 'includes recipes' do
    expect_any_instance_of(recipe).to receive(:include_recipe).with('bar')
  end
end

但是当我 运行 rspec 我得到以下错误:

foo::default
  includes recipes (FAILED - 1)

Failures:

  1) foo::default includes recipes
     Failure/Error: allow_any_instance_of(recipe).to receive(:include_recipe).with('bar')
       #<InstanceDouble(Chef::Recipe) (anonymous)> received unexpected message :ancestors with (no args)
     # ./vendor/cookbooks/foo/spec/recipes/default_spec.rb:32:in `block (2 levels) in <top (required)>'

Finished in 2.22 seconds (files took 1.72 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./vendor/cookbooks/foo/spec/recipes/default_spec.rb:43 # foo::default includes recipes

谁能阐明这个问题:

  1. chefspec 运行 可以指定所有包含的食谱的规格吗?如果是这样,我该如何配置?
  2. 如果前面的不可能,我如何解决上述问题并消除包含的食谱的收敛(将其他食谱视为黑盒)?

更新:

也尝试了解决方案 Stub (...) received unexpected message (...) with (no args) 但没有帮助,并返回了不同的错误:

foo::default
  includes recipes (FAILED - 1)

Failures:

  1) foo::default includes recipes
     Failure/Error: allow(recipe).to receive(:ancestors).and_return(true)
       the Chef::Recipe class does not implement the instance method: ancestors. Perhaps you meant to use `class_double` instead?
     # ./vendor/cookbooks/foo/spec/recipes/default_spec.rb:31:in `block (2 levels) in <top (required)>'
     # ./vendor/cookbooks/foo/spec/recipes/default_spec.rb:37:in `block (2 levels) in <top (required)>'

Finished in 1.33 seconds (files took 1.4 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./vendor/cookbooks/foo/spec/recipes/default_spec.rb:48 # foo::default includes recipes

转自腾思白评论:

If I understand you properly, what you wish really is to exclude 'bar' cookbook resources from coverage report, and for this it's documented in the coverage part of the Readme here using add_filter in the coverage.start! block. Chefspec does not load the tests for included cookbook, I don't know of a way to do this, including the helpers/stubs could be an idea, but it's too much guessing IMO.