Ну здесь на мой взгляд ответ один - это
SOLID и
clean architecture. Этот подход позволит вам разработать тестируемое и расширяемое приложение.
Например, то что ваше приложение обращается к БД из контроллеров это уже не есть гуд, так как для тестирования бизнес логики вам придется задействовать инфраструктуру, а именно http. По хорошему у вас должен быть слой бизнес логики, который инжектится в контроллер, а в слой бизнес логики должен инжектится, например слой доступа к данным. Таким образом вы можете тестировать любой слой независимо друг от друга, так как у вас будет слабая связанность компонентов системы.