Trying to Test a Private Method is a Signal That You Need Another Class
Sometimes I find myself wanting to write tests (or stubs) for a private method. It recently occurred to me that I should consider that impulse an indicator that there is another object hiding in my code. If the private method is sufficiently complicated that it requires direct testing, then the class is probably doing too much.
That code should be extracted to a new object that can be tested in isolation.
Imagine customer class that performs a credit check before possibly offering a loan.
class Customer
def should_offer_loan?
credit_score >= passing_credit_score
end
private
def credit_score
# Complicated stuff with a web service and database
# ...
end
def passing_credit_score
500
end
end
Trying to test the credit score method directly is an anti-pattern. We could
just make it public, but doing that only exposes an implementation detail. In this
domain, clients of the Customer
class don’t need to know the customer’s credit score:
its only used to determine if the customer is eligible for the loan.
Extracting a CreditCheck
class gives another object that can be tested
directly and in isolation. Its also now far easier to stub out the web-service and database calls
to allow faster tests.
Before reaching for a stub, or making a method needlessly public, consider if there is another object hiding out and waiting to be given a life of its own.