When should I use Injection Dependency and utility methods?

I have a Java EE project with a Spring IoC container.

I just found in the Utils static method of the Utils class sendMail(long list of params) . I don’t know why, but I feel that it would be better if we had a separate class (Spring bean with Singleton scope) that would be responsible for sending emails. But I can not find arguments that can confirm my position.

So, are there any pros (or cons) when using DI in this (fairly general) situation?

+4
source share
6 answers

If the classes to which you want to send email use the MailSender interface (sample name) instead of the static Utils.sendMail(...) method, then you can easily unit test these classes by replacing them in the breadboard / different implementation of MailSender in your unit tests, rather than using a real implementation.

This allows you to check the behavior of these classes when sending mail successfully, when an exception / error is caught, etc.

If the classes use a static method, like what you described, then you cannot unit test the behavior of these classes in isolation without sending an email, and at this point it is not an effective isolated unit test, since you will now depend on the behavior 1) mail sending code 2) outgoing mail server, etc.

+6
source

Yes! I will give you an example from my recent experience.

We recently switched a bunch of applications from direct email to using the database queue to send messages. Messages are queued in the database and then sent through a batch process. This gives us the ability to handle SMTP server failures, resend messages, control which messages can be sent from our dev server, check whether messages are actually sent, etc.

Something as simple as sending an email could certainly be something you might want to change in the future. Implementing an implementation would make it easier.

+5
source

Classes like Util that contain mishmash with usually static functions are usually not good. I even saw a class called UglyGlobals in one project that I was working on. At least they were honest about it! As a rule, you are right. Something like a mailing list is a great candidate for turning into a single bean that is being introduced.

+3
source

Spring Mail

First, I would like to advise you to take a look at the org.springframework.mail package . It provides a useful library for sending emails and serves as an abstraction to hide the specifics of basic mail systems.

And since you are already using spring, this will mean no pain in using this library if it provides everything you need to do with your application regarding sending mail.

Static methods against dependency injection

Using dependency injection gives you the ability to easily switch to other implementations. Static method calls closely connect your consumer implementation with the service that the consumer uses.

Consumer testing means that you will integrate consumer testing with the service, and not your consumer's testing unit in isolation. This makes you always depend on the core logic of these static methods and makes the tests possibly fail due to an error in one of these static methods.

0
source

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.

0
source

You want to avoid the static methods of the utility, which are state-dependent or have external effects that you in some situation (often testing) might want to avoid for any reason.

In this case, sending mail probably depends on the external state (availability of the mail server) and creates external effects that you might want to avoid (sending email). For development and testing, you probably don't want emails to send at all. In other cases, you may need to check if the email is sent, but how do you do it if the mail is actually sent? Set up a sophisticated system to check the actual email inbox for email?

If you enter an interface that represents MailSender , you can provide NoopMailSender that does nothing when you don’t need to send a sent email and a StubMailSender fake that collects a List<EmailMessage> emails that were sent through it when you want to check that certain emails were sent by your code.

0
source

Source: https://habr.com/ru/post/1308670/


All Articles