The most common question I get from developers is:
TDD sounds nice, but how do I deal with legacy code? There are just too many dependencies to deal with.
There is one true answer; one true path...
Legacy code is built upon countless dependencies. This is anathema to unit testing for the simple reason that you cannot get at the type under test without constructing many other types. And unfortunately the situation degrades exponentially.
The solution is to refactor. Let me repeat that with all the proper emphasis: The only way to achieve code coverage is by refactoring to the Single Responsibility Principle (SRP).
Once you have achieved a reasonable level of SRP you will introduce test doubles (e.g., dummy, mock, fake) and in short order attain code coverage.
But wait! How do I refactor my legacy code?
Just.Do.It. Although a good reference is Working Effectively With Legacy Code.