"Legacy code" is one of those questions which never have a great answer when confronted with (besides the
"Test only when you can, which will only be sometimes.." answer)
One of the coolest findings lately for me was TypeMock.NET. It was introduced to me by Eli Lopian, one of the head technology guys at Amdocs Israel.
It's a Mocking framework for .NET (much like NMock is) but it supports a very wide range of "unusual" scenarios.
For example, it allows one to "Mock" a real class, not just an interface.
It goes further by letting you "Mock" a type's static methods and essentially take over whenever someone instantiates a new instance of a particular type. This would come in very handy in situations like legacy code testing.
Imagine this:
You have a legacy class that uses a private member of type "Log". This "log" class does not support interfaces so you couldn't mock it directly with NMock and such.
Using TypeMock you can actually tell .NET that when a call to "new" on that object type is being done, it will instead instantiate your own mock object. That's some awesome power.
It can even go as further as mocking statics. Imagine that your legacy class is using static methods on the Log class, which you would like to "replace" with your own thus simulating various error modes and such. With TypeMock, it's a pretty easy deal.
I see this tool being used in situations where you would like to test your legacy code, which was not designed to be testable. Using TypeMock you could probably get away with 90% of your testing scenarios easily.
I do not see this as an aid to full blown TDD, however, because using TDD I would write code that would make it easy for me to Mock interfaces. Using TypeMock on code would usually mean a red flag for me as a developer, saying something along the lines of "Your interfaces and design are not generic enough to be testable, TypeMock is not the answer!".
I'm tempted to write a full article on this, and I just might. Meanwhile, this looks like a good start to using TypeMock.
Oh, and it's free (download requires registration).
One of the things I liked about it is how it's actually done: It uses the CLR profiler APIs to "intercept" JIT calls to create various objects. A downside for that is that there can only be one profiler active at a time, so you couldn't really run CLR profiler and TypeMock at the same time (I'm guessing).
Another "feature" right now is that it will not let you "mock" built-in framework types such as "Int32". (I actually tried mocking "Int.Parse" and it didn't work. Word is they are planning to do this for the next version, but I shudder to think about the security implications for this (or if it's even possible).