[JAVA] À propos de la conception de Spring Boot et de l'environnement de test unitaire

Aperçu

Cet article résume les réflexions sur la conception d'un environnement de test unitaire facile à implémenter et à maintenir dans une application Web qui utilise Spring Boot. Puisqu'il s'agit d'un article de conception, il n'aborde pas la façon d'écrire concrètement du code de test.

environnement

référence

Application de démonstration

Structure du projet

Comment couper le colis

Dans cette application de démonstration, les trois sous-packages suivants sont créés pour chaque couche. La division des couches en sous-packages facilite la création d'un environnement de test pour chaque couche.

src.main.java
  |
  +--- com.example.demo                          //★package root
  |     |
  |     +--- Application.java                    //★Main Application Class
  |     |
  |     +--- domain                              //★ Couche de domaine
  |     |     |
  |     |     +--- DatasourceConfig.java         //★ Configuration de la source de données
  |     |     |
  |     |     +--- entity                        //☆ Placez la classe d'entité JPA
  |     |     |
  |     |     +--- repository                    //☆ Placer l'interface du référentiel JPA
  |     |     |                                      (spring-data-jpa)
  |     |     +--- service                       //☆ Placez la classe de logique métier
  |     |           |
  |     |           +--- impl
  |     |
  |     +--- external                            //★ Couche externe
  |     |     |
  |     |     +--- service                       //☆ Placez la classe de logique métier
  |     |           |
  |     |           +--- impl
  |     |
  |     +--- web                                 //★ couche Web
  |           |
  |           +--- WebMvcConfig.java             //★ Configuration WebMvc
  |           +--- JacksonConfig.java            //★ Configuration de Jackson
  |           |
  |           +--- advice
  |           |     |
  |           |     +--- CustomControllerAdvice.java
  |           |
  |           +--- interceptor
  |           |     |
  |           |     +--- CustomHandlerInterceptor.java
  |           |
  |           +--- controller                     //☆ Classe de contrôleur de place
  |
src.java.resources
  |
  +--- application.yml


src.test.java
  |
  +--- com.example.demo
  |     |
  |     +--- domain
  |     |     |
  |     |     +--- DomainTestApplication.java    //★ Classe d'application principale pour le test de la couche de domaine
  |     |     |
  |     |     +--- entity
  |     |     |
  |     |     +--- repository
  |     |     |
  |     |     +--- service
  |     |           |
  |     |           +--- impl
  |     |
  |     +--- external
  |     |     |
  |     |     +--- ExternalTestApplication.java  //★ Classe d'application principale pour les tests de couche externe
  |     |     |
  |     |     +--- service
  |     |           |
  |     |           +--- impl
  |     |
  |     +--- web
  |           |
  |           +--- WebTestApplication.java       //★ Classe d'application principale de test de niveau Web
  |           |
  |           +--- controller
  |
src.test.resources
  |
  +--- application.yml

Classe de point d'entrée

Dans Spring Boot, il est recommandé de placer la classe d'application principale avec l'annotation d'application Spring Boot dans la racine du package (ou un package supérieur aux autres classes). Placer cette classe au-dessus des autres classes analysera automatiquement le composant subordonné (avec les annotations Component et Service) et les classes de configuration.

14.2 Locating the Main Application Class We generally recommend that you locate your main application class in a root package above other classes

Cette classe est un contenu général (commun), il n'y a donc rien de spécial à mentionner.

Application


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}
}

Configuration de la couche de domaine

La classe de configuration liée à la couche de domaine est placée directement sous le package de domaine. Cet exemple est une classe qui configure la source de données. Je ne l'ai pas configuré dans ce code, mais je suppose que c'est dans cette classe si vous devez personnaliser la source de données ou le gestionnaire de transactions.

DatasourceConfig


import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories
@EntityScan
public class DatasourceConfig {

  // nothing

}

En outre, bien que omis dans le code ci-dessus, vous pouvez spécifier les packages à analyser dans les basesPackages comme indiqué ci-dessous.

@EnableJpaRepositories(basePackages = {"com.example.demo.domain.repository"})
@EntityScan(basePackages = {"com.example.demo.domain.entity"})

Configuration du niveau Web

La classe de configuration liée à la couche Web est placée directement sous le package Web. Cet exemple montre une classe qui personnalise WebMvc et

WebMvcConfig


@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new CustomHandlerInterceptor())
            .addPathPatterns("/memo/**");
    }

}

Ceci est une classe pour personnaliser Jackson. Le code ci-dessous personnalise l'ObjectMapper, mais vous pouvez faire de même avec le fichier de configuration.

JacksonConfig


@Configuration
public class JacksonConfig {

    @Bean
    public Jackson2ObjectMapperBuilder objectMapperBuilder() {
        Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
        builder.serializationInclusion(JsonInclude.Include.NON_NULL)
            .indentOutput(true)
            .failOnUnknownProperties(false)
            .failOnEmptyBeans(false)
            .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
            .featuresToEnable(SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS);
        return builder;
    }

}

Code de test

Classe de point d'entrée

Préparez des classes de point d'entrée de code de test pour chaque couche. En préparant chaque couche, vous ne pouvez capturer que les dépendances requises.

Test de la couche de domaine

Plage de dépendance de test de niveau de domaine

La racine du package pour les tests de niveau domaine est com.example.demo.domain et la classe DomainTestApplication est le point d'entrée pour les tests.

src.main.java
  |
  +--- com.example.demo
  |     |
  |     +--- domain
  |           |
  |           +--- DatasourceConfig.java  //★ Configuration de la source de données
  |           |
  |           +--- entity
  |           |
  |           +--- repository
  |           |
  |           +--- service
  |                 |
  |                 +--- impl
  |
src.java.resources
  |
  +--- application.yml


src.test.java
  |
  +--- com.example.demo
  |     |
  |     +--- domain
  |           |
  |           +--- DomainTestApplication.java  //★ Classe d'application principale pour le test de la couche de domaine
  |           |
  |           +--- entity
  |           |
  |           +--- repository
  |           |
  |           +--- service
  |                 |
  |                 +--- impl
  |
src.test.resources
  |
  +--- application.yml

Classe d'application principale pour les tests

DomainTestApplication


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DomainTestApplication {
    public static void main(String[] args) {
        SpringApplication.run(DomainTestApplication.class, args);
    }
}

Test unitaire du référentiel (à l'aide de la base de données intégrée)

[DataJpaTest] pour le test unitaire du référentiel (https://docs.spring.io/spring-boot/docs/2.0.0.RELEASE/api/org/springframework/boot/test/autoconfigure/orm/jpa/DataJpaTest.html) Utilisez des annotations. Si vous ajoutez l'annotation DataJpaTest, la base de données intégrée sera utilisée quels que soient les paramètres de la source de données. (H2 est utilisé dans cette application de démonstration) De plus, au lieu d'EntityManager, TestEntityManager Est disponible.

@RunWith(SpringRunner.class)
@DataJpaTest
public class MemoRepositoryTests {

    @Autowired
    private TestEntityManager testEntityManager;
    @Autowired
    private MemoRepository memoRepository;

    //Code de test

}

Test d'intégration du référentiel (à l'aide d'une source de données définie)

Si vous souhaitez effectuer le test d'intégration à l'aide de la source de données définie dans le fichier de configuration au lieu de la base de données intégrée, [AutoConfigureTestDatabase](https://docs.spring.io/spring-boot/docs/2.0.0.RELEASE/api/ org / springframework / boot / test / autoconfigure / jdbc / AutoConfigureTestDatabase.html) Vous pouvez modifier le paramètre avec l'annotation.

@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
public class MemoRepositoryIntegrationTests {

    @Autowired
    private TestEntityManager testEntityManager;
    @Autowired
    private MemoRepository memoRepository;

    //Code de test

}
Entrée des données de test

Si vous souhaitez utiliser un fichier sql ou une instruction sql pour saisir des données de test, [Sql](https://docs.spring.io/spring-framework/docs/5.0.4.RELEASE/javadoc-api/org/springframework/test /context/jdbc/Sql.html) Les annotations sont disponibles. Les annotations peuvent être attachées aux classes et aux méthodes, mais si elles sont attachées aux deux comme décrit dans JavaDoc, les paramètres de méthode sont prioritaires.

Method-level declarations override class-level declarations.

@Sql(statements = {
    "INSERT INTO memo (id, title, description, done, updated) VALUES (11, 'test title 1', 'test description', false, CURRENT_TIMESTAMP)",
    "INSERT INTO memo (id, title, description, done, updated) VALUES (12, 'test title 2', 'test description', true, CURRENT_TIMESTAMP)",
    "INSERT INTO memo (id, title, description, done, updated) VALUES (13, 'test title 3', 'test description', false, CURRENT_TIMESTAMP)",
})
Utilisez TestEntityManager autre que DataJpaTest

AutoConfigureTestEntityManager Utilisez l'annotation Si tel est le cas, TestEntityManager peut être utilisé sans l'annotation DataJpaTest.

Test d'unité de service

Spring Runner n'est pas requis pour les tests unitaires des services car il ne dépend pas du Spring Framework. Les composants dont dépend la cible de test sont simulés (ou espionnés) dans Mockito.

public class MemoServiceImplTests {

    @Rule
    public MockitoRule rule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);

    @Mock
    private MemoRepository memoRepository;
    @InjectMocks
    private MemoServiceImpl sut;

    //Code de test

}

Test d'intégration de services

Utilisez l'annotation SpringBootTest pour les tests d'intégration de services Faire. De plus, étant donné que la fonction de serveur Web n'est pas nécessaire, WebEnvironment.NONE est spécifié pour webEnvironment. S'il est défini sur NONE, le serveur Web intégré ne démarrera pas. La source de données du fichier de configuration est utilisée pour accéder à la base de données. Vous pouvez utiliser l'annotation Sql mentionnée ci-dessus ou EntityManager avec le code ci-dessous pour saisir les données de test. Autres méthodes décrites dans 80. Database Initialization Il y a.

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
@Transactional
public class MemoServiceImplIntegrationTests {

    @Autowired
    private EntityManager entityManager;
    @Autowired
    private MemoServiceImpl sut;

    //Code de test

}

Test de couche externe

Plage de dépendance (impact) du test de couche externe

La racine du package pour les tests de niveau externe est com.example.demo.external et la classe ExternalTestApplication est le point d'entrée pour les tests.

src.main.java
  |
  +--- com.example.demo
  |     |
  |     +--- external
  |           |
  |           +--- service
  |                 |
  |                 +--- impl
  |
src.java.resources
  |
  +--- application.yml


src.test.java
  |
  +--- com.example.demo
  |     |
  |     +--- external
  |           |
  |           +--- ExternalTestApplication.java  //★ Classe d'application principale pour les tests de couche externe
  |           |
  |           +--- service
  |                 |
  |                 +--- impl
  |
src.test.resources
  |
  +--- application.yml

Classe d'application principale pour les tests

Excluez DataSourceAutoConfiguration de l'AutoConfiguration car le niveau externe est indépendant de la base de données.

ExternalTestApplication


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;

@SpringBootApplication(exclude = {
    DataSourceAutoConfiguration.class
})
public class ExternalTestApplication {
    public static void main(String[] args) {
        SpringApplication.run(ExternalTestApplication.class, args);
    }
}

Unité de service, test d'intégration

Puisqu'il s'agit d'une classe de test similaire au test du service de la couche domaine, elle est omise.

Test de niveau Web

Plage de dépendances de test de niveau Web

La racine du package pour les tests de niveau Web est com.example.demo.web et la classe WebTestApplication est le point d'entrée pour les tests.

src.main.java
  |
  +--- com.example.demo
  |     |
  |     +--- domain
  |     |     |
  |     |     +--- DatasourceConfig.java  //★ Configuration de la source de données
  |     |     |
  |     |     +--- entity
  |     |     |
  |     |     +--- repository
  |     |     |
  |     |     +--- service
  |     |           |
  |     |           +--- impl
  |     |
  |     +--- external
  |     |     |
  |     |     +--- service
  |     |           |
  |     |           +--- impl
  |     |
  |     +--- web
  |           |
  |           +--- WebMvcConfig.java  //★ Configuration WebMvc
  |           +--- JacksonConfig.java  //★ Configuration de Jackson
  |           |
  |           +--- advice
  |           |     |
  |           |     +--- MyControllerAdvice.java
  |           |
  |           +--- interceptor
  |           |     |
  |           |     +--- MyHandlerInterceptor.java
  |           |
  |           +--- controller
  |
src.java.resources
  |
  +--- application.yml


src.test.java
  |
  +--- com.example.demo
  |     |
  |     +--- domain
  |     |     |
  |     |     +--- entity
  |     |     |
  |     |     +--- repository
  |     |     |
  |     |     +--- service
  |     |           |
  |     |           +--- impl
  |     |
  |     +--- external
  |     |     |
  |     |     +--- service
  |     |           |
  |     |           +--- impl
  |     |
  |     +--- web
  |           |
  |           +--- WebTestApplication.java  //★ Classe d'application principale de test de niveau Web
  |           |
  |           +--- controller
  |
src.test.resources
  |
  +--- application.yml

Classe d'application principale pour les tests

Comme la couche Web dépend de la couche de domaine et de la couche externe, le package cible est spécifié dans scanBasePackages.

WebTestApplication


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication(scanBasePackages = {
    "com.example.demo.domain.service",
    "com.example.demo.external.service",
    "com.example.demo.web"
})
public class WebTestApplication {
    public static void main(String[] args) {
        SpringApplication.run(WebTestApplication.class, args);
    }
}

Test unitaire pour convertir une entité en Json

Dans le test unitaire de Json, ajoutez l'annotation JsonTest. Je vais l'utiliser. Il s'agit d'un test unitaire pour voir si le résultat de la conversion d'une entité en json est sérialisé comme prévu. Testez les boucles infinies si vous personnalisez la sérialisation avec les annotations JsonProperty ou JsonIgnore de Jackson, ou s'il existe des références mutuelles entre entités, en particulier avec les annotations liées à JPA (OneToMany, ManyToOne, etc.).

@RunWith(SpringRunner.class)
@JsonTest
public class MemoToJsonTests {

    @Autowired
    private JacksonTester<Memo> json;

    //Code de test

}

Test du contrôleur

WebMvcTest Utilisez des annotations. WebMvcTest peut utiliser MockMvc et WebClient (nécessite HtmlUnit pour la dépendance).

Le [MockBean] de Spring Boot (https://docs.spring.io/spring-boot/docs/2.0.0.RELEASE/api/org/springframework/boot/test) se moque des composants dont dépend le contrôleur testé /mock/mockito/MockBean.html) (Bean espion [SpyBean](https://docs.spring.io/spring-boot/docs/2.0.0.RELEASE/api/org/springframework/boot/test/mock /mockito/SpyBean.html)) Utilisez des annotations. Les objets simulés par MockBean sont ajoutés au contexte de l'application et injectés dans la cible de test (MemoController dans cet exemple).

@RunWith(SpringRunner.class)
@WebMvcTest(MemoController.class)
public class MemoControllerTests {

    @Autowired
    private MockMvc mvc;
    @Autowired
    private ObjectMapper objectMapper;

    @MockBean
    private MemoService memoService;

    //Code de test

}
Utilisez MockMvc autre que WebMvcTest

AutoConfigureMockMvc Utilisez l'annotation Si vous le faites, vous pourrez utiliser MockMvc sans l'annotation WebMvcTest.

Test d'intégration du contrôleur

Dans les classes de test qui utilisent l'annotation SpringBootTest, au lieu de RestTemplate, [TestRestTemplate](https://docs.spring.io/spring-boot/docs/2.0.0.RELEASE/api/org/springframework/boot/test/web /client/TestRestTemplate.html) est disponible. Importez la classe DatasourceConfig car le test d'intégration du contrôleur nécessite un accès à la base de données.

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@Import(value = {DatasourceConfig.class})
public class MemoControllerIntegrationTests {

    @Autowired
    private TestRestTemplate testRestTemplate;

    //Code de test

}
Remplacement de la source de données pendant le test d'intégration

En définissant une classe de paramètres comme le code ci-dessous, vous pouvez remplacer la source de données par la base de données intégrée dans n'importe quel test d'intégration.

@TestConfiguration
public class WebTestConfig {

    @Bean
    public DataSource datasource() {
        return new EmbeddedDatabaseBuilder()
                .setType(EmbeddedDatabaseType.H2)
                .setScriptEncoding("UTF-8")
                .addScripts("classpath:scripts/init.sql")
                .build();
    }

}

TestConfiguration La classe de configuration utilisant des annotations est SpringBootConfiguration. Puisqu'il n'est pas soumis à la détection automatique des annotations, il doit être importé manuellement.

@Import(value = {DatasourceConfig.class, WebTestConfig.class})

En passant, lors de la création d'un schéma ou de la saisie de données de test, il est difficile à utiliser car il doit être écrit en SQL qui peut être utilisé même dans une base de données intégrée.

Supplément

Vérifier la configuration automatique

Si vous définissez la propriété de débogage dans le fichier de paramètres, le journal de débogage sera généré. (La même chose s'applique si vous spécifiez -Ddebug dans les propriétés système)

debug: true

Le résultat de la configuration automatique "RAPPORT D'ÉVALUATION DES CONDITIONS" est émis dans le journal de débogage, vous pouvez donc vérifier l'état de la configuration.

============================
CONDITIONS EVALUATION REPORT
============================


Positive matches:
-----------------

   AopAutoConfiguration matched:
      - @ConditionalOnClass found required classes 'org.springframework.context.annotation.EnableAspectJAutoProxy', 'org.aspectj.lang.annotation.Aspect', 'org.aspectj.lang.reflect.Advice', 'org.aspectj.weaver.AnnotatedElement'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
      - @ConditionalOnProperty (spring.aop.auto=true) matched (OnPropertyCondition)

//réduction

Negative matches:
-----------------

   ActiveMQAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required classes 'javax.jms.ConnectionFactory', 'org.apache.activemq.ActiveMQConnectionFactory' (OnClassCondition)

//réduction

Exclusions:
-----------

    None

Unconditional classes:
----------------------

    org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration

//réduction

Remplacer le champ privé sous test

Mockito.Whitebox n'est pas disponible

Dans les tests unitaires avec Mockito 1.x, j'ai parfois vu du code de test qui remplaçait le champ privé sous test par une classe appelée Whitebox, mais depuis Mockito 2.1, cette classe n'est plus disponible.

Whitebox.setInternalState(sut, "someService", mockSomeService);

Dans Spring (Boot), l'annotation Value peut injecter la valeur de réglage dans le champ privé, je l'ai donc vue également utilisée dans de tels cas.

@Value("${app.someValue}")
private String someValue;

La raison pour laquelle l'équipe de développement de Mockito a supprimé Whitebox peut être trouvée dans les problèmes suivants, mais dans une traduction approximative, «l'utilisation facile de Whitebox a stimulé la production de masse de code de test de mauvaise qualité. Il semble que ce soit de.

Méthode alternative

Au printemps (Boot), au lieu de Whitebox, ReflectionTestUtils Vous pouvez utiliser des classes, mais si le remplacement basé sur la réflexion est mauvais, vous hésitez également à utiliser cette méthode.

Une autre alternative consiste à changer la visibilité du champ de privé à package privé. La classe de test étant généralement dans le même package que la classe testée, il est possible de réécrire les champs directement à partir du code de test. Il n'est pas rare d'étendre la visibilité pour faciliter les tests, par exemple VisibleForTesting pour Google Guava. Il existe une annotation (/google/common/annotations/VisibleForTesting.html). Étant donné que cette annotation est une annotation de marqueur, elle n'étend pas automatiquement la plage visible pendant le test.

Je ne suis pas familier avec le développement piloté par les tests et les techniques de test unitaire, donc je ne peux pas commenter le fait que l'utilisation de la réflexion est "mauvaise" et que la visibilité est "meilleure que".

Recommended Posts

À propos de la conception de Spring Boot et de l'environnement de test unitaire
Environnement de développement-développement Spring Boot-
Changer d'environnement avec Spring Boot application.properties et l'annotation @Profile
Comment écrire un test unitaire pour Spring Boot 2
[Spring Boot] Construction de l'environnement (macOS)
Construction de l'environnement Docker × Spring Boot
Utilisez Spring Test + Mockito + JUnit 4 pour le test unitaire Spring Boot + Spring Retry
Comment faire un test unitaire de Spring AOP
◆ Spring Boot + note de construction de l'environnement gradle
Écrire du code de test avec Spring Boot
Fonction de profil Spring et application Spring Boot.
À propos du test d'application RSpec (test unitaire)
Utiliser DBUnit pour le test Spring Boot
Exemple de code pour le test unitaire d'un contrôleur Spring Boot avec MockMvc
Redirection et test unitaire à l'aide de la lunette Spring Flash
Ordre du prétraitement et du post-traitement du test unitaire JUnit
Création d'un environnement de développement Spring Boot dans Vagrant
Introduire RSpec et écrire le code de test unitaire
Mémo de construction de l'environnement Spring Boot sur Mac
À propos du printemps ③
Effectuer un test de confirmation de transaction avec Spring Boot
HTTPS avec Spring Boot et Let's Encrypt
Le test Spring Boot @WebMvcTest active la sécurité par défaut de Spring Security
Construction de l'environnement de développement Java Spring Boot + Docker
Essayez Spring Boot 1 (Construction de l'environnement ~ Démarrage de Tomcat)
Test de validation de classe de formulaire avec Spring Boot
Ajoutez une botte de printemps et un dégradé à éclipse
Page d'erreur Spring Boot Whitelabel et réponse JSON
Testez le contrôleur avec Mock MVC dans Spring Boot
Résumé de ce que j'ai appris sur Spring Boot
Sortie des journaux de demande et de réponse avec Spring Boot
Divers tableau de correspondance de Spring Framework et Spring Boot
Créez des projets Spring Boot par environnement avec Gradle
Créer un environnement Spring Boot avec Windows + VS Code
Spring Boot + Spring Data JPA À propos des jointures de table multiples
Créer un environnement de développement Spring Boot avec docker
À propos de Spring AOP
Défi Spring Boot
À propos de Spring AOP
Forme de botte de printemps
[Printemps] Construction de l'environnement
Spring Boot Rappelez-vous
gae + botte à ressort
Plans pour prendre en charge JDK 11 pour Eclipse et Spring Boot
Intégration Tomcat, Apache et WebSocket intégrée à l'application Spring Boot
Essayez d'utiliser un conteneur DI avec Laravel et Spring Boot
Mémo d'utilisation de Spring Security: coopération avec Spring MVC et Boot
[Compatible JUnit 5] Ecrire un test en utilisant JUnit 5 avec Spring boot 2.2, 2.3
Spring Boot avec les paramètres du filtre de sécurité Spring et les points addictifs
[Spring boot] J'ai pensé au code testable par DI
SSO avec GitHub OAuth dans l'environnement Spring Boot 1.5.x
[JUnit 5] Ecrivez un test de validation avec Spring Boot! [Test de paramétrage]
Testez la classe injectée sur le terrain dans le test de démarrage Spring sans utiliser le conteneur Spring
Test unitaire de l'API Web et test d'intégration avec SpringBoot + Junit5, 4 modèles
Comment démarrer par environnement avec Spring Boot de Maven
Tentative de SSR Vue.js avec Spring Boot et GraalJS
J'ai écrit un test avec Spring Boot + JUnit 5 maintenant
Création d'un environnement de base de données avec Docker dans Spring Boot (IntellJ)
Connectez Spring Boot et Angular en toute sécurité avec OpenAPI Generator
Comparaison Hello World entre Spark Framework et Spring Boot