We recently introduced RSpec/InstanceVariable into our RuboCop configuration at Vox Pupuli. Using instance variables is not considered best practice so we are currently migrating away from them. Here is en example of the old code style:
before :each do
@resource = Puppet::Type.type(:package).new(
name: 'express',
ensure: :present
)
@provider = described_class.new(@resource)
@provider.class.stubs(:optional_commands).with(:npm).returns '/usr/local/bin/npm'
@provider.class.stubs(:command).with(:npm).returns '/usr/local/bin/npm'
end
The variables are later used, for example:
it 'should use package name by default' do
@provider.expects(:npm).with('install', '--global', 'express')
@provider.install
end
or:
it 'should use the source instead of the gem name' do
@resource[:source] = '/tmp/express.tar.gz'
@provider.expects(:npm).with('install', '--global', '/tmp/express.tar.gz')
@provider.install
end
The whole spec file can be seen here, the failing tests are documented here. I was digging around a bit, but didn’t really had a clue how to fix it. Dominic Cleal was so kind to provide a fix (the following replaces the :each block):
let :resource do
Puppet::Type.type(:package).new(
name: 'express',
ensure: :present
)
end
let :provider do
described_class.new(resource).tap do |provider|
provider.class.stubs(:optional_commands).with(:npm).returns '/usr/local/bin/npm'
provider.class.stubs(:command).with(:npm).returns '/usr/local/bin/npm'
end
end
This allows us to access provider and resource as normal variables in the rest of the spec test. The fixed version is available here.