C'est @ Autowired
, que j'utilise absolument lors de l'écriture de code au printemps.
Récemment, il semble que l'injection de constructeur soit recommandée au lieu de l'injection de champ.
Essayez google pour savoir pourquoi l'injection de constructeur est recommandée en premier lieu. Il y a plusieurs raisons, mais celle dont j'étais le plus convaincu était "ça? N'est-ce pas un effort de test unitaire?", J'ai donc écrit à ce sujet.
L'échantillon est trop adapté, mais s'il existe une classe qui envoie un tel e-mail.
MailService.java
import org.springframework.mail.MailSender;
import org.springframework.mail.SimpleMailMessage;
@RestController
@RequestMapping(path="/mail")
public class MailService {
@Autowired
MailSender mailSender;
@PostMapping
public void send() {
SimpleMailMessage msg = new SimpleMailMessage();
msg.setFrom("[email protected]");
msg.setTo("[email protected]");
msg.setSubject("Hello World");
msg.setText("Welcome to my world.");
mailSender.send(msg);
}
}
J'écrirai le code de test.
MailServiceTest.java
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class MailServiceTest {
@InjectMocks
MailService mailService;
@Mock
MailSender mailSender;
@Captor
ArgumentCaptor<SimpleMailMessage> msgCaptor;
@Test
public void test() {
//Exécution de la méthode testée
mailService.send();
//Parmi les méthodes testées, mailSender#send a été exécuté une fois
//Au fait, saisissez l'argument
verify(mailSender, times(1)).send(msgCaptor.capture());
//Validez le contenu de l'argument
SimpleMailMessage msg = msgCaptor.getValue();
assertThat(msg.getFrom(), is("[email protected]"));
assertNotNull(msg.getTo());
assertThat(msg.getTo().length, is(1));
assertThat(msg.getTo()[0], is("[email protected]"));
assertThat(msg.getSubject(), is("Hello World"));
assertThat(msg.getText(), is("Welcome to my world."));
}
}
Dans une classe avec injection de champ, serait-il écrit comme ça? J'espère y être habitué, mais j'oublie à chaque fois comment écrire Captor, et si je ne fais pas de commentaire (même s'il y a un commentaire), je ne peux pas le lire plus tard, et c'est ennuyeux en premier lieu.
MailService.java
public class MailService {
private final MailSender mailSender;
@Autowired
public MailService(MailSender mailSender) {
this.mailSender = mailSender;
}
//Ce qui suit est omis
@ RunWith
ou @ SpringBootTest
.MailServiceTest.java
public class MailServiceTest {
/**
*Créez votre propre classe simulée mailSender
*/
private class MailSenderMock implements MailSender {
SimpleMailMessage simpleMessage;
@Override
public void send(SimpleMailMessage simpleMessage) throws MailException {
this.simpleMessage = simpleMessage;
}
@Override
public void send(SimpleMailMessage... simpleMessages) throws MailException {
}
}
@Test
public void test() {
//Passez la classe fictive pour créer une instance
MailSenderMock mailSenderMock = new MailSenderMock();
MailService mailService = new MailService(mailSenderMock);
//Exécution de la méthode testée
mailService.send();
//Vérification
SimpleMailMessage msg = mailSenderMock.simpleMessage;
assertThat(msg.getFrom(), is("[email protected]"));
assertNotNull(msg.getTo());
assertThat(msg.getTo().length, is(1));
assertThat(msg.getTo()[0], is("[email protected]"));
assertThat(msg.getSubject(), is("Hello World"));
assertThat(msg.getText(), is("Welcome to my world."));
}
}
Dans l'exemple, la classe fictive est écrite en tant que classe interne, mais vous pouvez créer un fichier de classe individuellement. Vous pouvez le faire avec Mockito.mock, cependant. C'était la fin de l'histoire que Mockito était ennuyeux, mais ... (Mockito.mock () peut être bon pour les classes où vous n'avez rien à faire.)
Il semble qu'il n'y ait pas beaucoup de différence car la classe cible de test de l'échantillon est trop simple, mais j'ai pensé qu'il serait facile de ne pas se moquer d'elle avec Mockito. De plus, comme il ne dépend plus de SpringBoot, JUnit ne fonctionnera pas en raison des paramètres de propriété ou du manque de base de données.
Par exemple, vous pouvez avoir environ 3 @ Autowired
et changer le comportement pour un seul test unitaire.
Dans ce cas, définissez-le sur @ SpringBootTest
et définissez la classe qui ne modifie pas le comportement sur @ Autowired
dans la classe de test.
Dans ce cas, cela dépend de Spring Boot. Je veux écrire du code de test comme un test d'intégration de Controller, mais il y a une classe qui me gêne! Parfois, je pense que cette méthode est également bonne.
MailServiceTest.java
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class MailServiceTest {
@Autowired
HogeSerice hogeService;
@Autowired
FugaService fugaService;
private class MailSenderMock {
//Abréviation
}
@Test
public void test() {
//Passez la classe fictive pour créer une instance
MailSenderMock mailSenderMock = new MailSenderMock();
MailService mailService = new MailService(mailSenderMock, hogeService, fugaService);
//Abréviation