Are You Using Mock Objects as Bandaids?

Ideally a clean design should prevent the need to mock. Wanting to mock indicates your system details are leaking into your business objects.

Mock objects are a bandaid covering up a design that needs a second look.

Business Objects

These are where your business rules live e.g. how much money can a loan officer give vs a supervisor. You'll probably like to store these values in an external system like a data store or parameter server.

You then might be tempted to have the business object access the store, and this is where your details are leaking. You'll now want to mock the store so you can test the business logic.

Details

Details are your frameworks and external systems. Things like databases, messaging frameworks and guis. If you can look at a business object and tell what user interface or data store you are using, you have leaky details.

    public interface LoanRules {
        Integer getMaxLoan();
    }

    public class LoanOfficerRules() implements LoanRules {
        public Integer getMaxLoan () {
            ParameterStore store = ParameterStore.build()
            return store.getLoanOfficerMaxLoanAmount();    
        }
    }

    public class SupervisorLoanRules implements LoanRules {
        public Integer getMaxLoan () {
            ParameterStore store = ParameterStore.build()
            return store.getSupervisorMaxLoanAmount();    
        }
    }

The implementations of LoanRules are leaking details. Business objects should not know where parameters and configurations come from.

To test LoanRules implementations you'll have to dynamically mock ParameterStore.

Parameter Store is a detail. Wanting to mock details is a strong design smell urging you to revisit your design.

I'll provide one possible solution soon, but for now ...

Treat mock objects as a design smell.