This week's book giveaway is in the OO, Patterns, UML and Refactoring forum. We're giving away four copies of Refactoring for Software Design Smells: Managing Technical Debt and have Girish Suryanarayana, Ganesh Samarthyam & Tushar Sharma on-line! See this thread for details.
I'm writing some code that deals with System.console(). For console.reader(), it is fine as I can pass in a reader. For console.readPassword(), I'm at a loss. I had to resort to creating a mock subclass that returns a "test password.". That feels like a hack. Any better ideas? I could wrap it an interface, but that's not any better.
The problem is that Console is final, lacks an interface and lacks a constructor. And as an added bonus System.console() returns null in a JUnittest.
What a total nuisance this is! It wouldn't be so bad if Console weren't final.
Have you tried using one of the more elaborate mocking frameworks such as PowerMock for swapping out final classes? I haven't actually tried this framework for final classes but it works well enough for mocking static methods (using some Reflection Wizardry).
Alternatively you could write an adaptor for the System interaction which can be swapped out with a fake in your testing. This is basically wrapping it in an interface as you already mentioned. However, how do you then test the adaptor?
One one hand I would say that by using something like PowerMock you could achieve a technically more complete test coverage, but it does add a good degree of noise to your test cases as the API is relatively verbose. On the other hand introducing an adaptor for your System interaction is the more elegant solution, and the one most discussed in the books on Testing that I've read, but does leave you with an adaptor that still has a dependency on Console that you can't work with.
A combination of each may be the way to go. Wrap it up in an adaptor so that the rest of your system, and test, only has to deal with the dreamy adaptor interface, then use PowerMock to test the in's and out's of your interaction with System and Console while keeping the scope of those tests small within the bounds of the adaptor implementation.