How to spec a private method
Solution 1:
I always take this approach: I want to test the public API my class exposes.
If you have private methods, you only call them from the public methods you expose to other classes. Hence, if you test that those public methods work as expected under all conditions, you have also proven that the private methods they use work as well.
I'll admit that I've come across some especially complex private methods. In that extreme case you want to test them, you can do this:
@obj.send(:private_method)
Solution 2:
For the private methods that need code coverage (either temporarily or permanently), use the rspec-context-private gem to temporarily make private methods public within a context.
gem 'rspec-context-private'
It works by adding a shared context to your project.
RSpec.shared_context 'private', private: true do
before :all do
described_class.class_eval do
@original_private_instance_methods = private_instance_methods
public *@original_private_instance_methods
end
end
after :all do
described_class.class_eval do
private *@original_private_instance_methods
end
end
end
Then, if you pass :private
as metadata to a describe
block, the private methods will be public within that context.
class Example
private def foo
'bar'
end
end
describe Example, :private do
it 'can test private methods' do
expect(subject.foo).not eq 'bar'
end
end