Si vous voulez être très pratique pour tester les API et l'intégrer dans CI pour vérifier chaque engagement, alors le IT inclus avec Spring Boot est certainement le meilleur choix.
Écrivez un cas de test rapidement
@Runwith (springrunner.class) @springboottest (webenvironment = Springboottest.webenvironment.random_port) @activeProfiles ({Profils.env_it}) classe publique DeMointegrationTest {@Autowired Private Fooservice Fooservice; @Test public void test () {System.out.println ("testé"); }}Parmi eux, Springboottest définit certaines configurations lors de l'exécution. Le code ci-dessus utilise des ports aléatoires, et bien sûr, il peut également prédéfinir des ports, comme celui-ci
@Springboottest (weenvironment = Springboottest.webenvironment.defined_port, Properties = {"Server.port = 9990"})ActiveProfiles force l'utilisation du profil informatique. D'après une meilleure pratique, les adresses des bases de données ou d'autres composants de ressources configurées par le profil informatique doivent être isolées de l'environnement de développement ou de mise en scène. Parce que lorsqu'il passe dans de nombreuses situations, nous devons effacer les données de test.
Vous pouvez constater qu'un tel cas peut être injecté avec Autowired dans n'importe quel service souhaité. En effet, Spring charge tout le contexte, ce qui est le même que l'environnement d'exécution réel, y compris la base de données, le cache et d'autres composants. Si vous pensez que vous n'avez pas besoin de toutes les ressources pendant les tests, vous pouvez supprimer la configuration correspondante dans le profil. Il s'agit d'un environnement de fonctionnement complet, la seule différence est qu'elle s'arrête automatiquement une fois le cas d'utilisation terminé.
Testez une API REST
Je recommande vivement une bibliothèque à ajouter à Gradle
TestCompile 'io.rest-assuré: REST-assuré: 3.0.3' '
Soutenez JsonPath, ce qui est très utile. Cliquez ici pour des documents spécifiques
@Sql (scripts = "/testdata/users.sql")@testpublic void test001login () {string username =" [email protected] "; Chaîne mot de passe = "Demo"; JWTAUThenticationRequest request = new JWTAUTHEnticationRequest (nom d'utilisateur, mot de passe); Response Response = donnée (). ContentType (contentType.json) .body (request) .when (). Post ("/ auth / login"). Alors () .staturScode (httpstatus.ok.value ()) .Extract () .Response (); AssertThat (Response.Path ("Token"), est (isNull.notnullValue ())); AssertThat (Response.Path ("Expiration"), est (isNull.notnullValue ()));} @SQL est utilisé pour effectuer des données de test d'insertion SQL avant les tests. Notez que given().body() est passé dans un objet Java jwtUthenticationRequest, car REST-assuré vous aidera automatiquement à utiliser Jackson pour sérialiser l'objet en une chaîne JSON. Bien sûr, vous pouvez également mettre le JSON converti dans le corps, l'effet est le même.
Le résultat de retour est capturé par une réponse, puis les données peuvent être obtenues à l'aide de JSONPath pour la vérification. Bien sûr, il existe une autre manière plus intuitive, qui peut obtenir la réponse complète via Response.assstring (), puis la désérialiser en un objet Java pour la vérification.
À ce stade, le plus élémentaire il est achevé. L'ajout d'un test d'étape Gradle à Jenkins peut réaliser des tests chaque fois que le code est soumis.
Quelques situations compliquées
Données mixtes
C'est le plus facile à se produire. Un projet dispose de nombreux développeurs, et chaque développement rédigera son propre cas informatique, alors que se passe-t-il s'il y a un impact entre les données. C'est facile à comprendre. Par exemple, dans un scénario où un lot de test écrit, la méthode de vérification finale consiste à voir si la quantité de données écrites est de 10 000 lignes. Ensuite, un autre Dev a écrit d'autres cas et s'est avéré ajouter de nouvelles données à ce tableau, qui s'est transformé en lignes 10W + 1, de sorte que le cas écrit en lots ne pourrait pas s'échapper.
Pour empêcher cette situation, nous utilisons chaque classe de test pour effacer les données. Puisqu'il s'agit d'une opération basée sur la classe, vous pouvez écrire une classe de base pour le résoudre.
@Runwith (springrunner.class) @springboottest (Webenvironment = Springboottest.webenvironment.random_port) @activeProfiles ({Profils.env_it}) Public Résumé Class BaseIntegrationTest {private static jdbcTemplate jdbctEmplate; @Autowired public void setDataSource (dataSource dataSource) {jdbCTemplate = new JDBCTemplate (dataSource); } @Value ("$ {local.server.port}") Protected int port; @Before public void setupenv () {restassured.port = port; Restassured.basepath = "/ api"; Restassured.baseuri = "http: // localhost"; Restassured.config = restassured.config (). Httpclient (httpclientConfig.httpclientConfig (). HttpMultiPartMode (httpMultiparmode.browser_compatible)); } public void Teardownenv () {donné (). ContentType (contentType.json) .When (). Post ("/ Auth / Logout"); } @Afterclass public static void cleandb () lève sqlexception {ressource ressource = new classPathResource ("/ testData / cleandb.sql"); Connexion connexion = jdbctemplate.getDataSource (). GetConnection (); ScriptUtils.ExECUTESQLScript (connexion, ressource); connection.close (); }}@AfterClass utilise JDBCTemplate pour exécuter un CleanDB.SQL, qui efface toutes les données de test de cette manière.
@ Value("${local.server.port}") doit également être mentionné, car le port est aléatoire, assuré de repos ne sait pas à quel port la demande est envoyée. Ici, utilisez @Value pour obtenir le numéro de port actuel et définissez-le sur Restassured.port pour résoudre ce problème.
Comment traiter les données partagées
L'exécution d'un complet peut nécessiter des dizaines de classes et des centaines de méthodes. Que se passe-t-il si certaines données sont nécessaires pour tous les cas et doivent être effacées uniquement après que tous les cas ont été exécutés? En d'autres termes, ce type de nettoyage des données n'est pas basé sur la classe, mais sur une course à la fois. Par exemple, les données utilisateur initiales, la bibliothèque de la ville, etc.
Nous avons joué une astuce intelligente et utilisé la voie de migration
@ Configuration @ conditionalOnClass ({dataSource.class}) classe publique UpgradeAutoConfiguration {public static final String Flyway = "Flyway"; @Bean (name = Flyway) @Profile ({Env_it}) public upgradeservice CleanAndupgradeService (dataSource dataSource) {upgradeService upgradeService = new FlywayupgradeService (dataSource); try {upgradedeservice.cleanandupgrade (); } catch (exception ex) {logger.error ("Flyway a échoué!", ex); } return upgradeService; }} Vous pouvez voir que lorsque le profil est celui-ci, Flyway supprimera toutes les tables et exécutera le script de mise à niveau à son tour, créant ainsi une table de données complète, qui est bien sûr vide. Dans le chemin d'essai du projet, ajoutez une énorme version de SQL, afin que Flyway puisse insérer des données de test communes à la fin, telles que src/test/resources/db/migration/V999.0.1__Insert_Users.sql , résoudre parfaitement divers problèmes de données.
résumé
L'utilisation du service de test intégré dans Spring Boot peut rapidement vérifier l'API. Je n'ai pas à démarrer le service, puis cliquez sur la page manuelle pour tester mon API. Je communique directement avec mes collègues frontaux le format de demande et j'écris un cas pour le vérifier.
Bien sûr, il existe également un inconvénient de cette méthode, à savoir qu'il n'est pas pratique de tester le système. Auparavant, les cas de test API de la société ont été rédigés par JMeter, ce qui serait beaucoup plus pratique lors des tests de performance.