Правильно ли я делаю, что все кроме работы с БД выношу в отдельные классы и потом внедряю как DI?
Все эти DI, IoC придумали для слабой связанности. Т.е. их использование оправдано, если Вы хотите разорвать сильную зависимость между какими-то модулями или объектами, т.к. в будущем ожидаете изменений или хотите добавить возможность тестирования какого-то участка кода.
Если Вам не принципиально ни то, ни другое, то не стоит доводить до фанатизма)
И кстати, если хотят модульной тестируемости, то зависимость от бд рвут в первую очередь. Иначе получатся интеграционные тесты, зависимые от данных в бд. Ну и если в будущем предполагается, что захотят перейти на другую бд, то в этом случае тоже, работу с ней желательно вынести в абстракцию и потом инжектить.
Это Вам надо читать про чистую архитектуру. 
Можно подходить из таких соображения класс который легко тестируется уже сделан правильно. 
Что нужно тестировать в классе?  Только логику которую мы написали.  Строго говоря на вход мы подаем объекты заглушки и тестируем только свою логику.  
Этот подход сочитается с принципом единственной ответственности, те класс выполняет только свои дела.  
Применяя DI правильно,  у Вас получится такое разделение: компоненты - независимые переиспользуемые части и сборщики - те кто собирают компоненты в нужную систему и конфигурацию. 
Вы получите ясность и переиспользуемость.  Плюс гибкость.