Skip to content

Instantly share code, notes, and snippets.

@acrmp
Created November 10, 2012 00:05
Show Gist options
  • Save acrmp/4049159 to your computer and use it in GitHub Desktop.
Save acrmp/4049159 to your computer and use it in GitHub Desktop.
Mocking out a library in Chef

Example of mocking out a library in Chef so you can test the provider in isolation.

If you want to test the library itself you can do more normal Ruby things.

diff --git a/providers/instrument.rb b/providers/instrument.rb
index 5197ef5..c7b96b6 100644
--- a/providers/instrument.rb
+++ b/providers/instrument.rb
@@ -17,10 +17,14 @@
# limitations under the License.
#
+def librato(email, token)
+ Librato::Metrics.new(email, token)
+end
+
def load_current_resource
email = new_resource.email || node.librato_metrics.email
token = new_resource.token || node.librato_metrics.token
- @librato = Librato::Metrics.new(email, token)
+ @librato = librato(email, token)
@streams = if new_resource.metric
[
{
require 'chefspec'
require_relative 'provider_loader'
describe 'instrument' do
include ProviderLoader
module MockLibrato
attr_writer :librato
def librato(*args)
@librato
end
end
let (:chef_run) { ChefSpec::ChefRunner.new.converge 'librato_metrics::default' }
let(:instrument) do
lwrp({
:resource_name => 'my_instrument',
:cookbook_name => 'librato_metrics',
:provider => 'instrument',
:resource => 'instrument',
:mixin => MockLibrato}).tap{|i| i.librato = double(Librato::Metrics)}
end
it "should be created if it doesn't exist" do
streams = [{'metric' => 'foo', 'source' => '*', 'group_function' => 'sum'}]
instrument.new_resource.streams(streams)
instrument.load_current_resource
instrument.librato.should_receive(:instrument_exists?).with('my_instrument').and_return(false)
instrument.librato.should_receive(:create_instrument).with('my_instrument', streams)
instrument.action_create
end
it "shouldn't be created if it does exist" do
instrument.load_current_resource
instrument.librato.should_receive(:instrument_exists?).with('my_instrument').and_return(true)
instrument.librato.should_not_receive(:create_instrument)
instrument.action_create
end
it "should use a metric if one is provided" do
metric = {'metric' => 'foo', 'source' => '*', 'group_function' => 'average'}
instrument.set_new_resource(metric)
instrument.load_current_resource
instrument.librato.should_receive(:instrument_exists?).with('my_instrument').and_return(false)
instrument.librato.should_receive(:create_instrument).with('my_instrument', [metric])
instrument.action_create
end
end
module ProviderLoader
def cookbook_files(type)
chef_run.run_context.cookbook_collection.values.map do |c|
c.send("#{type}_filenames".to_sym).map do |p|
{:cookbook_name => c.metadata.name, :filename => p}
end
end.flatten
end
def filename_for(cookbook_name, type, name)
cookbook_files(type).find do |p|
p[:cookbook_name] == cookbook_name and
Pathname.new(p[:filename]).basename.sub_ext('').to_s == name
end[:filename]
end
def lwrp(options)
provider_file = filename_for(options[:cookbook_name], :provider, options[:provider])
resource_file = filename_for(options[:cookbook_name], :resource, options[:resource])
clazz = Chef::Provider.build_from_file(options[:cookbook_name], provider_file, chef_run.run_context)
resource_clazz = Chef::Resource.build_from_file(options[:cookbook_name], resource_file, chef_run.run_context)
prov = clazz.new(resource_clazz.new(options[:resource_name], chef_run.run_context), chef_run.run_context)
prov.extend(options[:mixin]) if options[:mixin]
prov.extend(Module.new do
def set_new_resource(atts)
atts.each_pair{|key, value| new_resource.send(key, value)}
end
end)
prov
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment