Recherche…


Comment tester une application Spring simple

Nous avons un exemple d'application d'amorçage Spring qui stocke les données utilisateur dans MongoDB et nous utilisons les services Rest pour récupérer les données.

Il y a d'abord une classe de domaine, c'est-à-dire POJO

@Document
public class User{
    @Id
    private String id;

    private String name;

}

Un référentiel correspondant basé sur Spring Data MongoDB

public interface UserRepository extends MongoRepository<User, String> {
}

Puis notre contrôleur utilisateur

@RestController
class UserController {
 
    @Autowired
    private UserRepository repository;
 
    @RequestMapping("/users")
    List<User> users() {
        return repository.findAll();
    }
 
    @RequestMapping(value = "/Users/{id}", method = RequestMethod.DELETE)
    @ResponseStatus(HttpStatus.NO_CONTENT)
    void delete(@PathVariable("id") String id) {
        repository.delete(id);
    }
 
    // more controller methods
}

Et enfin notre application Spring Boot

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

Si, disons que John Cena, The Rock et TripleHHH étaient les trois seuls utilisateurs de la base de données, une demande à / users donnerait la réponse suivante:

$ curl localhost:8080/users
[{"name":"John Cena","id":"1"},{"name":"The Rock","id":"2"},{"name":"TripleHHH","id":"3"}]

Maintenant, pour tester le code, nous allons vérifier que l'application fonctionne

@RunWith(SpringJUnit4ClassRunner.class)   // 1
@SpringApplicationConfiguration(classes = Application.class)   // 2
@WebAppConfiguration   // 3
@IntegrationTest("server.port:0")   // 4
public class UserControllerTest {

    @Autowired   // 5
    UserRepository repository;

    User cena;
    User rock;
    User tripleHHH;

    @Value("${local.server.port}")   // 6
    int port;

    @Before
    public void setUp() {
        // 7
        cena = new User("John Cena");
        rock = new User("The Rock");
        tripleHHH = new User("TripleHH");

        // 8
        repository.deleteAll();
        repository.save(Arrays.asList(cena, rock, tripleHHH));

        // 9
        RestAssured.port = port;
    }

    // 10
    @Test
    public void testFetchCena() {
        String cenaId = cena.getId();

        when().
                get("/Users/{id}", cenaId).
        then().
                statusCode(HttpStatus.SC_OK).
                body("name", Matchers.is("John Cena")).
                body("id", Matchers.is(cenaId));
    }

    @Test
    public void testFetchAll() {
        when().
                get("/users").
        then().
                statusCode(HttpStatus.SC_OK).
                body("name", Matchers.hasItems("John Cena", "The Rock", "TripleHHH"));
    }

    @Test
    public void testDeletetripleHHH() {
        String tripleHHHId = tripleHHH.getId();

        when()
                .delete("/Users/{id}", tripleHHHId).
        then().
                statusCode(HttpStatus.SC_NO_CONTENT);
    }
}

Explication

  1. Comme pour tout autre test basé sur Spring, nous avons besoin de SpringJUnit4ClassRunner pour SpringJUnit4ClassRunner un contexte d'application.
  2. L'annotation @SpringApplicationConfiguration est similaire à l'annotation @ContextConfiguration en ce sens qu'elle est utilisée pour spécifier le ou les contextes d'application à utiliser dans le test. En outre, il déclenchera la logique de lecture des configurations, propriétés et autres éléments spécifiques du démarrage du ressort.
  3. @WebAppConfiguration doit être présent pour indiquer à Spring qu’un WebApplicationContext doit être chargé pour le test. Il fournit également un attribut pour spécifier le chemin d'accès à la racine de l'application Web.
  4. @IntegrationTest est utilisé pour indiquer à Spring Boot que le serveur Web intégré doit être démarré. En fournissant des paires nom-valeur séparées par des deux-points ou des équations, toutes les variables d'environnement peuvent être remplacées. Dans cet exemple, le "server.port:0" remplacera le paramètre de port par défaut du serveur. Normalement, le serveur commence à utiliser le numéro de port spécifié, mais la valeur 0 a une signification particulière. Lorsqu'elle est définie sur 0, elle indique à Spring Boot d'analyser les ports de l'environnement hôte et de démarrer le serveur sur un port disponible aléatoire. Cela est utile si différents services occupent différents ports sur les machines de développement et le serveur de génération qui pourrait potentiellement entrer en collision avec le port de l'application, auquel cas l'application ne démarrera pas. Deuxièmement, si nous créons plusieurs tests d'intégration avec des contextes d'application différents, ils peuvent également entrer en conflit si les tests s'exécutent simultanément.
  5. Nous avons accès au contexte de l’application et nous pouvons utiliser l’auto-activation pour injecter n'importe quel bean Spring.
  6. La valeur @Value("${local.server.port}”) sera résolue au numéro de port utilisé.
  7. Nous créons des entités que nous pouvons utiliser pour la validation.
  8. La base de données MongoDB est effacée et réinitialisée pour chaque test afin de toujours valider par rapport à un état connu. L'ordre des tests n'étant pas défini, il est probable que le test testFetchAll () échoue s'il est exécuté après le test testDeletetripleHHH ().
  9. Nous demandons au Rest Assuré d'utiliser le bon port. C'est un projet open source qui fournit une DSL Java pour tester des services reposants.
  10. Les tests sont implémentés en utilisant Rest Assured. nous pouvons implémenter les tests en utilisant TestRestTemplate ou tout autre client http, mais j'utilise Rest Assured car nous pouvons écrire une documentation concise en utilisant RestDocs

Chargement de différents fichiers yaml [ou properties] ou remplacement de certaines propriétés

Lorsque nous utilisons @SpringApplicationConfiguration il utilisera la configuration de application.yml [propriétés] qui, dans certaines situations, n'est pas appropriée. Donc, pour remplacer les propriétés, nous pouvons utiliser l’annotation @TestPropertySource .

@TestPropertySource(
        properties = {
                "spring.jpa.hibernate.ddl-auto=create-drop",
                "liquibase.enabled=false"
        }
)
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(Application.class)
public class ApplicationTest{

    // ...

}

Nous pouvons utiliser l'attribut de propriétés de @TestPropertySource pour remplacer les propriétés spécifiques souhaitées. Dans l' exemple ci - dessus , nous prépondérants propriété spring.jpa.hibernate.ddl-auto pour create-drop . Et liquibase.enabled à false .

Chargement d'un fichier yml différent

Si vous souhaitez charger un fichier yml différent pour le test, vous pouvez utiliser l'attribut locations sur @TestPropertySource .

@TestPropertySource(locations="classpath:test.yml")
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(Application.class)
public class ApplicationTest{

    // ...

}

Options alternatives

Option 1:

Vous pouvez également charger un fichier yml différent en plaçant un fichier yml sur test > resource répertoire de test > resource

Option 2:

Utiliser l'annotation @ActiveProfiles

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@ActiveProfiles("somename")
public class MyIntTest{
}

Vous pouvez voir que nous @ActiveProfiles annotation @ActiveProfiles et que nous passons le nom de fichier comme valeur.

Créez un fichier appelé application-somename.yml et le test chargera ce fichier.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow