DI makes it easy to make fun of your implementation for writing tests. For example, suppose you want to test the reset password stream. With the hard-coded Utils.sendMail (), your test code will be forced to make the SMTP mock server, read and parse the email, and then click the reset password link. If you used DI, you can pass the mock Emailer object. In this way, you can write ultrafast unit tests without worrying about external integrations.
You can also easily change implementations. For example, the Google App Engine has its own sendMail API, so it will be difficult for you to maintain the GAE version and the non-GAE version at the same time. (For argument's sake, just assume that migration to GAE is so simple that it is not obvious.)
Finally, your code is more modular. A specific class (ResetPassword) can depend only on Util.sendMail (), but Util can be a kitchen sink with methods to do everything under the sun. So, if you want to reuse ResetPassword in another project, you need to copy the entire Utils class, as well as several dependent jars that Utils should work. This is not a good option.
source share