RSpec: Stub private method
Solution 1
should_receive(:method)
works whether the visibility of :method
is public or private.
Solution 2
You can use allow_any_instance_of
method to stub or mock any instance of a class
for e.g. you have a class
named Foo
with some private
methods than you can do something like this
allow_any_instance_of(Foo).to receive(:private_method) do
#do something
end
In case if there you have module
also, you can do something like this
allow_any_instance_of(Module::Foo).to receive(:private_method) do
#do something
end
You can find more details about allow_any_instance_of()
method at Official Documentation
Solution 3
Why do you want to test the private methods? They're private for a reason; to prevent access from external calls. Testing the public methods that rely on the private methods should be sufficient.
Comments
-
23tux almost 2 years
I try to test a class with RSpec2, that has some private methods, which are called from some public methods. I test the public methods with
@foo.should_receive(:start_training).exactly(2).times
if they are called and how often. My problem is, that this approach doesn't work with private methods. So, is there any way to use sth like
@foo.send(:private_method)
in combination withshould_receive
? Or any other syntax? -
23tux about 11 yearseehmm... I'm sure that it works. Can you explain it more what you mean?
-
23tux about 11 yearsI tried it out, when I try to call should_receive with a private method, I get
private method
start_training' called for #<Run:0x007f7f7e2ebe68>` -
Justin Aiken about 11 yearsCould you post a bit more code? In the spec I'm working on atm, I'm should_receive'ing private methods with no issues...
-
23tux about 11 yearsSilly me, I called the private method from another step of the test. So you were right,
should_receive
works in both cases, public AND private methods. Thanks! -
André Herculano about 10 yearsI'm pretty sure it worth it testing private methods. Otherwise, if you have 10 public methods that rely on that one private method, you could end up repeating yourself testing the behavior of all public those methods.
-
Damien Roche almost 9 years@AndréHerculano yes, but you should be testing behaviour, not implementation. You would test the returns of those public methods, regardless of what private methods they use.
-
23tux over 5 yearsusing
allow_any_instance_of
is considered a bad practise, see rubydoc.info/gems/rubocop-rspec/1.6.0/RuboCop/Cop/RSpec/… -
courtsimas over 4 yearsThey didn't say they wanted to test private methods. But the test relied on some private methods that he wanted to stub out.
-
23tux over 4 yearsas pointed out in the answer above, you can stub private methods, and it has nothing to do with protected methods. Furthermore stubbing with
allow_any_instance_of
is considered a code smell and should be avoided (also recommended by Rubocop rubydoc.info/gems/rubocop-rspec/1.6.0/RuboCop/Cop/RSpec/…) -
A moskal escaping from Russia over 4 yearsWhy is it considered a smell @23tux?
-
Tim Kretschmer about 3 years@SebastianPalma it's not. it's his opinion and the one of some rubocop fanatics. rubocop also say it's bad if your model in rails is > 250 lines (by default). some huge ass god models are easy 1000 and they are still slim. don't take rubocop for granted.