Refactoring poorly written code that has little abstraction and does not separate concerns can greatly reduce the risk of defects and speed up future development. Adding unit tests during this small scale redesign process can have all the benefits of unit testing during the initial implementation.
Adding unit tests to poorly written code without any refactoring achieves none of this. Instead it acts as a barrier to refactoring and improving code. If a method or class serves multiple purposes and abstracts no underlying complexities then it serves as an entry point for defects and often expands the cost of adding or refining features. Unit testing such a method or class makes it more difficult to refactor and remove these deficiencies.
Lastly passing unit tests for such code do not provide confidence that the code is working as it should. The passing tests instead act as a false positive. If the code has no clear definition of what it should do then a test that says it is doing what it should does not help.
I could test the ability of a hammer to dig a hole and then use that hammer turn a screw. In this scenario my test gives me false confidence in the ability of the hammer to the job for which it is being used. All the while the intended usage of the hammer is missed. The real answer to this scenario is to use a screw driver. This would be similar to refactoring code. Then test the ability of the screw driver to screw in screws. This would be similar to unit testing.
Check out my blog for more of my musings upon technology and various other topics.