I tend to find that higher level integration or end to end tests are a better approach at dealing with this type of code.
Whilst in theory it is better to separate the coordinator from the algorithm, in practice when somebody throws a huge muddy code base at you it's better not to start tearing up the insides until you've got something that gives you confidence that you haven't broken anything when you refactor.
Unit tests present something of a chicken/egg problem in this regard. In such cases you need to refactor heavily to be able to use them. You will need refactoring safety to do this, however. They don't provide refactoring safety until you do it, though. Dilemma.
On the two projects where I followed the "high level tests first" approach I ultimately ended up not decomposing after that anyway since the integration tests ended up being sufficient and all but eliminated the pain of having un-decomposed code.
That is, I could have safely rewritten it so that it was "unit test friendly" but I started to wonder if tearing up the insides of a code base in order to accommodate the intransigence of unit tests was really such a great idea after all given the risk and extremely high cost and the fact that integration tests did the job they were supposed to just fine.
It's a controversial topic though. Not everybody agreed with me on this. Some people view unit tests as inherently "cleaner" (not sure why) and others are militant about a test taking 50ms being so much better than a test that takes 5 seconds that tearing up the insides was justified. In both cases, I suspect it was a case of principles overriding the underlying cost/benefit analysis.