Aperçu
- Qu'est-ce que les tests unitaires
- Pourquoi faire des tests unitaires ?
- Quelques malentendus sur les tests unitaires
- Quels sont les principaux frameworks de tests unitaires ?
- Appréciation des exemples de chaque framework
- Comparaison de différents frameworks
- Comment faire des tests unitaires
- Réflexion sur les problèmes
1. Qu’est-ce que les tests unitaires ?
Wikipédia le décrit ainsi : En programmation informatique, les tests unitaires, également appelés tests de modules, sont un test permettant de tester l'exactitude des modules de programme. Une unité de programme est le plus petit composant testable d’une application. En programmation procédurale, une unité est un programme, une fonction, un processus, etc. ; pour la programmation orientée objet, la plus petite unité est une méthode, y compris les méthodes des classes de base, des classes abstraites ou des classes dérivées.
La différence entre les tests unitaires et les tests d'intégration
Les cadres de test et les outils utilisés pour les tests unitaires et les tests d'intégration sont pour la plupart les mêmes.
La première chose sur laquelle il faut se mettre d’accord est que qu’il s’agisse de tests unitaires ou de tests d’intégration, ce sont des tests automatisés. Afin de mieux le distinguer, nous pouvons le comprendre ainsi : il se trouve dans le même entrepôt de code que le code de production et le code de test unitaire, écrits par les étudiants en développement eux-mêmes, et a des effets réels sur l'environnement externe (base de données, fichiers). système, système externe, file d'attente de messages, etc.) Les tests appelés sont des tests d'intégration.
Le tableau suivant compare également les différences entre les tests unitaires, les tests d'intégration et les tests au niveau du système (y compris les tests de bout en bout, les tests de liens, les tests de régression automatisés, les tests d'interface utilisateur, etc.) sous différents angles.
Test de l'unité | Tests d'intégration | Tests au niveau du système | |
---|---|---|---|
Écrivains | développer | développer | développement/test |
lieu d'écriture | Dans l'entrepôt du code de production | Dans l'entrepôt du code de production | À l'intérieur de l'entrepôt de codes de production/À l'extérieur de l'entrepôt de codes de production |
Temps d'écriture | Avant la publication du code | Avant la publication du code | Avant la publication du code/Après la publication du code |
coût d'écriture | Faible | milieu | haut |
Difficulté à écrire | Faible | milieu | haut |
vitesse de rétroaction | Extrêmement rapide, quelques secondes | Niveau plus lent et minute | Lent, niveau jour |
Zone de couverture | Couverture des lignes de code 60 à 80 % Couverture des succursales 40 à 60 % | Couverture du niveau fonctionnel | lien d'assurance de base |
dépendance à l'environnement | Niveau de code, indépendant de l'environnement | S'appuyer sur l'environnement quotidien ou local | Dépend de l'environnement de préparation ou de production |
Simulation de dépendance externe | Toutes les simulations | simulation partielle | Pas de simulation, utilisez entièrement l'environnement réel |
Deuxièmement, pourquoi avons-nous besoin de tests unitaires ?
avantage:
-
Améliorez la stabilité du système et facilitez les itérations.
-
Propice à une compréhension approfondie de la technologie et des affaires.
-
Le coût d’un seul test est faible et la vitesse est rapide.
-
Le test unique est le meilleur document automatisé et exécutable.
-
La conception basée sur des tests uniques améliore la simplicité et la standardisation du code, garantissant une refactorisation sûre. Une fois le code modifié, le test unique peut toujours réussir, ce qui peut renforcer la confiance des développeurs.
-
Commentaires rapides, découvrez les problèmes plus rapidement, localisez les défauts plus rapidement et avec plus de précision que les tests d'intégration et réduisez les coûts de réparation.
Faibles coûts de développement :
1,
L'idée la plus intuitive :
2,
Cette idée est en effet la plus intuitive. Mais cela ne pense qu'au premier niveau. Si nous additionnons toutes les étapes du processus de développement , nous constaterons que cela ressemble à ceci :
Derrière le processus de développement, des bugs peuvent survenir dans presque tous les processus. Plus les bogues sont générés plus tard dans le processus, plus le programmeur doit investir de temps et d'activité par rapport à la phase de développement, et les risques qu'il supporte sont également les plus élevés.
L'image ci-dessous illustre également deux problèmes : premièrement, 85 % des défauts sont générés dès la phase de conception du code ; deuxièmement, plus la découverte des bugs est tardive, plus le coût est élevé, qui augmente de façon exponentielle. Ce genre de cas de « coût exponentiel » arrive souvent : lorsque l'on corrige un bug, trois autres bugs peuvent suivre, communément appelés : la correction plante.
Par conséquent, des bogues peuvent être détectés dès les premiers tests unitaires, ce qui permet non seulement d'économiser du temps et des efforts, d'améliorer l'efficacité du processus de développement, mais également de réduire le risque et le temps nécessaire aux modifications répétées.
3. Quelques malentendus sur les tests unitaires
Zhihu https://zhuanlan.zhihu.com/p/547068206 2, 5, 6, 9, 11
Mythe 1 : les tests unitaires ralentissent le processus de développement
La vérité est la suivante : comme tout nouvel outil, s'habituer aux tests unitaires prend un peu de temps, mais dans l'ensemble, les tests unitaires font gagner du temps et en font perdre moins. En effet, effectuer des tests de régression permet de faire avancer le processus de développement de manière continue et sans aucun souci. Si des tests unitaires sont effectués lors des builds quotidiens, ces tests ne prendront pas de temps de développement.
Idée fausse n°2 : une fois le projet terminé, le travail investi dans les tests unitaires est gaspillé
Pas du tout. Si vous avez déjà réutilisé du code, vous réaliserez que tout ce que vous faites est un atout.
Le fait est que lorsque vous utilisez du code que vous avez précédemment écrit pour un autre projet dans un projet, ou que vous modifiez ce code, vous pouvez utiliser les mêmes tests unitaires ou modifier ces tests unitaires. Il n'y a aucun problème à utiliser des extraits de code de test similaires dans le même projet.
Mythe 3 : les tests unitaires sont une perte de temps
Vous devez comprendre ce qu’est une perte de temps ?
Corriger les mêmes vulnérabilités encore et encore
Écrire ou réécrire le code de validation tout au long du processus de développement
Un bug est corrigé, pour ensuite qu'un autre bug apparaisse ailleurs, sorti de nulle part.
J'ai été accidentellement interrompu lors de l'écriture du code et je ne sais pas quoi faire.
La résistance aux tests unitaires est compréhensible, mais de nombreux développeurs ne vanteront pas la qualité des tests unitaires tant qu'ils n'auront pas terminé un projet en les utilisant.
La vérité est la suivante : vous n’avez besoin d’écrire un test unitaire qu’une seule fois, mais de l’exécuter plusieurs fois. Cela n'a rien à voir avec les modifications que vous apportez à un autre code. L’investissement initial sera rentable à long terme.
Malentendu 4 : les tests unitaires n'aident pas au débogage du programme ou ne peuvent pas empêcher l'apparition de vulnérabilités.
Ce n'est absolument pas le cas. Les tests unitaires peuvent faciliter le débogage du programme car vous pouvez vous concentrer sur le code problématique, résoudre les problèmes, puis fusionner à nouveau le code modifié. Cela empêche également l'introduction de vulnérabilités lors de l'ajout de fonctionnalités et évite que des problèmes ne se reproduisent de manière frustrante, en particulier lors de la programmation utilisant une approche orientée objet. Les tests unitaires ne peuvent pas garantir l’élimination à 100 % des vulnérabilités, mais ils constituent un bon moyen de réduire les vulnérabilités.
Le fait est que même si les tests unitaires ne peuvent pas résoudre tous les problèmes que vous rencontrez lors du débogage, lorsque vous trouvez une vulnérabilité, le code isolé dans le test unitaire peut faciliter la correction de la vulnérabilité. Selon les fans inconditionnels des tests unitaires parmi les développeurs, le plus grand avantage des tests unitaires est qu'ils rendent le débogage du programme très facile et simple.
Malentendu 5 : l'utilisation de tests unitaires pour le débogage de programmes n'offre pas une couverture complète
Ce n’est pas parce que vous ne pouvez pas déboguer l’intégralité du code que la couverture du débogage n’est pas complète. L'utilisation de tests unitaires pour le débogage de programmes est au moins meilleure que les autres types de débogage. En fait, les tests unitaires présentent un avantage très important : (sinon les éliminent grandement, du moins) ils réduisent considérablement le nombre de vulnérabilités signalées que j'ai mentionnées ci-dessus. La reproduction de bugs peut être très frustrant lors du développement et du débogage de programmes. Grâce aux tests unitaires, vous pouvez réduire la fréquence d'introduction de nouvelles vulnérabilités lors de l'ajout, de la modification et de la suppression de fonctionnalités. Le débogage a toujours été une « couverture complète », en particulier lorsque les appareils ou systèmes sur lesquels le programme s'exécute sont très différents.
La vérité est la suivante : en particulier lorsqu’il s’agit de vulnérabilités, les tests unitaires peuvent garantir que vous trouvez des vulnérabilités qui n’ont jamais été signalées. Et lorsque vous déboguez le programme, vous n'avez pas besoin de vérifier l'intégralité du code, il vous suffit de modifier les endroits où se produisent les vulnérabilités.
4. Quels sont les principaux frameworks de tests unitaires ?
- Junit : Junit est l'un des frameworks de tests unitaires Java les plus couramment utilisés. Il fournit un ensemble d'API simples et faciles à utiliser pour écrire et exécuter facilement des tests unitaires. Les principaux avantages de Junit incluent la facilité d'apprentissage et d'utilisation, une large utilisation, une écologie riche, etc., mais il lui manque certaines fonctions avancées, telles que des objets simulés, etc.
- Mockito : Mockito est un framework de tests unitaires Java pour les objets fictifs, qui aide les développeurs à créer et à gérer des objets fictifs pour des tests unitaires réels. Les principaux avantages de Mockito incluent des fonctions puissantes, faciles à apprendre et à utiliser, la prise en charge des extensions, etc., mais cela peut entraîner des problèmes de performances.
- Spock : Spock est un framework de tests unitaires Java basé sur le langage Groovy. Il fournit un ensemble de DSL (langage spécifique à un domaine) concis et lisible qui permet aux développeurs d'écrire et d'exécuter facilement des tests unitaires. Les principaux avantages de Spock incluent la facilité de lecture et de maintenance, la fourniture d'une riche bibliothèque d'assertions, la prise en charge des tests basés sur les données, etc., mais il nécessite une prise en charge supplémentaire du compilateur Groovy. Cependant, sa compatibilité est relativement mauvaise. Si la version dépendante est légèrement erronée, des erreurs inexplicables seront signalées et les invites ne seront pas évidentes, ce qui rendra difficile la résolution des problèmes.
- TestNG : TestNG est un framework de test Java, similaire à Junit. Il fournit un ensemble de fonctions de test puissantes, notamment la prise en charge des tests multithread, des tests basés sur les données, des tests de groupe, etc. Les principaux avantages de TestNG incluent des fonctionnalités riches, une expansion facile et la possibilité de s'intégrer à divers outils d'intégration continue. Cependant, il lui manque certaines fonctionnalités avancées, telles que les objets fictifs.
- PowerMock : PowerMock est un framework d'extension pour les tests unitaires Java qui aide les développeurs à écrire des tests unitaires plus flexibles. Les principaux avantages de PowerMock incluent la prise en charge des tests de méthodes statiques, de méthodes privées, etc., faciles à apprendre et à utiliser, et peuvent être utilisés avec d'autres frameworks de test, etc., mais cela peut introduire plus de complexité et de coûts de maintenance.
5. Exemples d'utilisation de chaque framework
JUnit:
import org.junit.Test;
import static org.junit.Assert.*;
public class MyTest {
@Test
public void testSomething() {
// 执行测试代码
assertEquals(2 + 2, 4);
}
}
Moqueur :
import static org.mockito.Mockito.*;
public class MyTest {
@Test
public void testSomething() {
// 创建模拟对象
MyObject mockObject = mock(MyObject.class);
// 设置模拟对象的行为
when(mockObject.someMethod()).thenReturn("Hello World");
// 执行测试代码
String result = mockObject.someMethod();
// 断言结果是否符合预期
assertEquals(result, "Hello World");
}
}
Spock:
import spock.lang.Specification
import spock.lang.Subject
class CalculatorSpec extends Specification {
@Subject
Calculator calculator = new Calculator()
def "test add method"() {
given:
int a = 2
int b = 3
when:
int result = calculator.add(a, b)
then:
result == 5
}
def "test subtract method"() {
given:
int a = 5
int b = 2
when:
int result = calculator.subtract(a, b)
then:
result == 3
}
}
class Calculator {
int add(int a, int b) {
return a + b
}
int subtract(int a, int b) {
return a - b
}
}
TestNG:
import org.testng.annotations.Test;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.AfterMethod;
import static org.testng.Assert.assertEquals;
public class MyTestNGTest {
@BeforeMethod
public void setUp() {
// 在测试方法执行前执行的代码
}
@AfterMethod
public void tearDown() {
// 在测试方法执行后执行的代码
}
@Test
public void testAddition() {
int result = Calculator.add(2, 3);
assertEquals(result, 5);
}
@Test
public void testSubtraction() {
int result = Calculator.subtract(5, 3);
assertEquals(result, 2);
}
}
class Calculator {
public static int add(int a, int b) {
return a + b;
}
public static int subtract(int a, int b) {
return a - b;
}
}
PowerMock:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.powermock.api.mockito.PowerMockito.*;
@RunWith(PowerMockRunner.class)
@PrepareForTest(Example.class)
public class ExampleTest {
@Test
public void testPrivateMethod() throws Exception {
Example spy = spy(new Example());
doReturn("mocked value").when(spy, "privateMethod");
String result = spy.publicMethod();
assertEquals("mocked value called from publicMethod", result);
}
}
class Example {
public String publicMethod() throws Exception {
return privateMethod() + " called from publicMethod";
}
private String privateMethod() {
return "privateMethod";
}
}
Ce qui précède n'est qu'un exemple simple. En utilisation réelle, il est nécessaire de configurer et d'écrire du code de test en fonction de la situation spécifique.
6. Comparaison de différents frameworks
Cadre et fonctionnalités | Fonction simulée | Prise en charge des méthodes privées et des méthodes statiques | lisibilité du code | coût d'apprentissage | notions grammaticales | Évolutivité et personnalisation | Intégration et compatibilité | Documentation et soutien communautaire | Performances et stabilité |
---|---|---|---|---|---|---|---|---|---|
Junit | × | × | Haute lisibilité | Faible | Simple et facile à comprendre | Pauvre | spring-test est intégré par défaut | bien | bien |
Mockito | √ | × | Haute lisibilité | Faible | API simple, excellente documentation | Pauvre | spring-test est intégré par défaut | bien | bien |
TestNg | × | √ | Lisibilité moyenne | moyen | Syntaxe simple, mais configuration des dépendances lourde | Fournit une multitude de points d’extension et de mécanismes de plug-in | bien | En général, il existe relativement peu de documentation | bien |
PowerMock | √ | √ | Le code est long et complexe et peu lisible | moyen | La syntaxe est relativement complexe | Fournit une multitude de points d’extension et de mécanismes de plug-in | bien | bien | bien |
Spock | √ | √ | Besoin de connaître la syntaxe Groovy | haut | Basé sur le langage Groovy, syntaxe complexe | Fournit une multitude de points d’extension et de mécanismes de plug-in | Mauvaise compatibilité | bien | bien |
Résumé : Il est recommandé d'utiliser Junit+Mockito
- Junit et TestNG sont principalement utilisés pour les tests d'intégration. PowerMock et Spock ont des coûts d'apprentissage élevés, des codes longs et une lisibilité compliquée, qui ne sont pas propices à la lecture.
- Il dispose d'une API simple, d'une excellente documentation et d'un grand nombre d'exemples, ce qui facilite la prise en main et la complexité du code n'est pas élevée.
- Il est très lisible, le code est simple et facile à comprendre, il bénéficie d'un bon support communautaire et il est facile de trouver des solutions lorsque des problèmes surviennent.
- spring-boot-starter-test intègre les frameworks Junit et Mockito par défaut.
- Pour les méthodes privées et statiques, elles peuvent être simulées en utilisant une combinaison de Junit, PowerMock et Mockito.
7. Comment réaliser un seul test ?
1. Scénarios d'utilisation d'un seul test
- Taux de réutilisation du code . Plus le taux de réutilisation du code est élevé, plus il est nécessaire de mettre en œuvre des tests uniques, et plus il est nécessaire d'améliorer les exigences pour les tests uniques. Par conséquent, ces codes sont référencés par de nombreuses entreprises, donc une fois qu'ils rencontrent des problèmes, ils affecteront de nombreuses parties commerciales. Il est plus rentable de mettre en œuvre des tests uniques sur ces codes.
- Taux de changement d'entreprise . Plus l’activité évolue rapidement, moins il est approprié de recourir à des tests uniques. Si l'activité évolue très rapidement et que le contenu d'un seul test doit être modifié quelques jours après sa mise en ligne, vous devez alors non seulement modifier le code métier, mais également le code de test unique, ce qui représente le double de la charge de travail.
- Taux de rotation du personnel . Le taux de changement de personnel fait référence aux changements de personne en charge d'un certain module. Si la personne responsable d'un certain module change fréquemment, il ne convient pas à un test unique. Étant donné que le nouveau responsable doit passer beaucoup de temps à se familiariser avec le contenu du test unique, le temps de développement des exigences deviendra très long.
- Importance commerciale . Plus l'activité est essentielle, plus il est nécessaire de mettre en œuvre des tests uniques et plus il est nécessaire de répondre à des normes élevées. Parce que la stabilité et la robustesse du cœur de métier sont définitivement très importantes pour l’entreprise, et qu’un seul test peut en effet améliorer la stabilité et la robustesse du système dans la plus petite unité.
Nous ne pouvons pas examiner les quatre dimensions de mesure mentionnées ci-dessus isolément, mais devons porter des jugements complets basés sur la situation réelle pour arriver à la norme la plus appropriée !
2. De bons tests unitaires doivent respecter les principes.
①Principe AIR
Remarque : Lorsque le test unitaire est exécuté en ligne, cela ressemble à de l'air (AIR), mais il est très essentiel de garantir la qualité du test. D'un point de vue macro, un bon test unitaire présente les caractéristiques d'automatisation, d'indépendance et d'exécution reproductible.
- R : Les tests unitaires automatiques doivent être entièrement automatisés et non interactifs. Les cas de test sont généralement exécutés régulièrement et le processus d'exécution doit être entièrement automatisé pour être significatif. Un test dont le résultat nécessite une révision manuelle n’est pas un bon test unitaire.
- I : Independent (indépendance) maintient l'indépendance des tests unitaires. Afin de garantir que les tests unitaires sont stables, fiables et faciles à maintenir, les cas de tests unitaires ne doivent pas s'appeler les uns les autres et ne peuvent pas non plus s'appuyer sur l'ordre d'exécution. Contre-exemple : méthode2 doit s'appuyer sur l'exécution de méthode1, et le résultat de l'exécution est saisi en tant que paramètre de méthode2.
- R : Les tests unitaires répétables (répétables) peuvent être exécutés à plusieurs reprises et ne peuvent pas être affectés par l'environnement externe. Remarque : les tests unitaires sont généralement placés en intégration continue, et les tests unitaires seront exécutés à chaque fois que le code est archivé. Si un seul test dépend de l’environnement externe (réseau, service, middleware, etc.), il conduira facilement à l’indisponibilité du mécanisme d’intégration continue. Exemple positif : afin de ne pas être affecté par l'environnement externe, il est nécessaire de modifier la dépendance SUT en injection lors de la conception du code et d'utiliser un framework DI tel que Spring pour injecter une implémentation locale (mémoire) ou une implémentation Mock pendant les tests. .
②PREMIER principe
1. F-Fast (rapide)
Les tests unitaires doivent pouvoir s'exécuter rapidement. Parmi les différentes méthodes de test, les tests unitaires sont ceux qui s'exécutent le plus rapidement. Les tests unitaires pour les grands projets doivent généralement s'exécuter en quelques minutes.
2. I-Indépendant (indépendant)
Les tests unitaires doivent pouvoir s'exécuter indépendamment. Les cas de tests unitaires ne dépendent pas les uns des autres ni de ressources externes.
3. R-Répétable (répétable)
Les tests unitaires doivent pouvoir s'exécuter de manière stable et répétée, et les résultats de chaque exécution doivent être stables et fiables.
4. S-SelfValidating (auto-vérification)
Les tests unitaires doivent être automatiquement vérifiés par les cas d'utilisation et ne peuvent pas s'appuyer sur une vérification manuelle.
5. T-en temps opportun
Les tests unitaires doivent être écrits, mis à jour et maintenus en temps opportun pour garantir que les cas d'utilisation peuvent garantir de manière dynamique la qualité à mesure que le code métier change.
3. Écrivez le code de test unitaire conformément aux principes BCDE pour garantir la qualité de livraison du module testé.
- B : Test de frontière, de valeur limite, y compris les limites de boucle, les valeurs spéciales, les points temporels spéciaux, l'ordre des données, etc.
- C : Corrigez, corrigez la saisie et obtenez les résultats attendus.
- D : Conception, combinée aux documents de conception pour rédiger des tests unitaires.
- E : Erreur, forcer la saisie d'informations d'erreur (telles que des données illégales, des processus anormaux, une saisie non autorisée par l'entreprise, etc.) et obtenir les résultats attendus.
4. Quels scénarios nécessitent l’écriture de tests uniques ?
Le code incrémentiel du cœur de métier, des applications principales et des modules principaux garantit la réussite des tests unitaires.
Les tests unitaires sont le moyen le plus élémentaire de développement logiciel, et l'une des idées les plus importantes dans le développement logiciel est l'idée de superposition. Chaque module de haut niveau est composé de plusieurs modules de bas niveau. S'il est assemblé avec des modules de bas niveau instables, les modules de haut niveau deviendront également peu fiables. Tout comme le royaume des mathématiques, il existe plusieurs axiomes de base, qui sont strictement construits couche par couche à travers des preuves. En outre, lorsque nous écrivons des affaires, nous devrions accorder plus d'attention à la réflexion en couches du modèle traditionnel à trois niveaux de contrôleur, de service et de dao, plutôt que de dire de manière dogmatique que toutes les entreprises ont ces trois couches. En prenant l’idée hiérarchique comme idéologie directrice, il existe des niveaux commerciaux plus complexes et des niveaux commerciaux moins simples.
Contrôleur -> service -> Interface externe du gestionnaire
— - - - - - - - - - - - - - -> Base de données Dao
Contrôleur : responsable de l'acceptation des demandes et du renvoi des réponses, ainsi que de la simple vérification des paramètres. Pour la logique sans vérification, aucun test unique n'est requis. Une logique de vérification complexe nécessite un seul test. Principalement utilisé pour les tests d'intégration
Service : sert de bloc de construction. Il est responsable de l'organisation de la logique métier, du traitement de la logique métier, du traitement des requêtes de la couche Contrôleur et de l'accès à la couche et au gestionnaire DAO. Il doit écrire des tests uniques.
Gestionnaire : ① Responsable de la coordination de plusieurs composants de la couche de service et du traitement des interactions entre les couches de service, nécessitant un test unique. ② Encapsulez l'interface externe et sans logique de traitement supplémentaire, aucun test unique n'est requis. ③Interagir avec la couche Dao et contrôler les transactions nécessite un seul test.
Dao : Effectuer des opérations liées à la base de données. Une logique complexe nécessite l'écriture de tests uniques, uniquement destinés à récupérer des données ou à les mettre à jour, et fondamentalement, aucun test unique n'est effectué.
Comment effectuer un test unique de la couche DAO sans polluer la base de données de test ?
-
Utiliser des bases de données intégrées : vous pouvez utiliser des bases de données intégrées, telles que H2, HSQLDB, etc., pour les tests unitaires. Ces bases de données embarquées peuvent s'exécuter en mémoire et ne polluent donc pas les données de la base de production.
-
Utiliser l'annulation de transaction : vous pouvez utiliser l'annulation de transaction pour vous assurer que le test ne pollue pas les données de la base de données. Avant le démarrage de la méthode de test, une transaction est lancée. Une fois le test terminé, la transaction est annulée afin que toutes les données modifiées soient restaurées à l'état d'avant le test, évitant ainsi la pollution des données. (Utilisation recommandée)
@RunWith(SpringRunner.class) @SpringBootTest public class UserServiceTest { @Autowired private UserService userService; @Test @Transactional public void testAddUser() { User user = new User(); user.setName("John Doe"); userService.addUser(user); // perform assertion User savedUser = userService.getUserByName(user.getName()); Assert.assertNotNull(savedUser); } }
-
Utiliser des outils de migration de bases de données : vous pouvez utiliser des outils de migration de bases de données, tels que Flyway, Liquibase, etc., pour les tests unitaires. Ces outils peuvent créer automatiquement une nouvelle instance de base de données avant chaque test et utiliser des scripts de migration de base de données pour initialiser les données, évitant ainsi le problème de pollution des données.
-
Créez une image Docker et démarrez une base de données.
En bref, le but de l'écriture de tests unitaires est de garantir l'exactitude et la fiabilité de chaque module. Ce n'est que lorsque chaque module a été vérifié par des tests unitaires qu'il peut être combiné en un tout stable et fiable.
8. Questions à débattre :
1. Dans les projets existants, le code est déroutant et il est difficile d'écrire des tests uniques, et il ne peut pas être annulé et réécrit. Comment ajouter élégamment des tests uniques ?
2. Après avoir écrit le test unitaire, si la fonction change, devez-vous d'abord changer le code ou écrire le test unitaire ?
Les tests et le codage peuvent être comparés à deux jambes humaines. La question devient donc : dois-je marcher avec ma jambe gauche ou ma jambe droite en premier ? Je pense que tout le monde pensera que la réponse à cette question n'a pas de sens, mais si vous réfléchissez à marcher avec précaution, vous constaterez que la coordination des jambes gauche et droite est la clé de notre marche. Si les pas sont longs, une jambe est boiteux, ou un pied saute, ils sont tous en mauvais état. Par analogie avec les tests unitaires, il en va de même pour le codage piloté par les tests et les tests d'optimisation du codage. Un codage gonflé, c'est comme faire un pas trop grand ; un mauvais test unique signifie qu'une jambe est boiteuse ; si vous n'écrivez pas un seul test, c'est un jeu sur une seule jambe.