[JAVA] Assertions JUnit et API Matcher

Aperçu

Dans JUnit, c'est un élément responsable de la vérification de la valeur. Comprenez «assertion» et «Matcher API».

Qu'est-ce qu'une assertion?

L'assertion a le sens d'affirmation et d'affirmation dans une traduction littérale.

JUnit peut être grossièrement divisé

  1. Définition des conditions préalables et des résultats attendus
  2. Exécution de la cible de test
  3. Vérification comparative du résultat attendu et du résultat de l'exécution

Un test unitaire est effectué dans les trois étapes ci-dessus. Qu'est-ce qu'une assertion dans JUnit? Il s'agit du troisième mécanisme pour effectuer une "vérification de comparaison entre les résultats supposés et les résultats d'exécution".

Dans le code réel, utilisez-le comme suit.

Exemple d'assertion.java


int expected = 1;
int actual = calc();
assertThat(actual, is(expected));

En écrivant comme ça, le test Affirmez que le réel est attendu (confirmez que la valeur mesurée est une valeur attendue). Peut être écrit en langue naturelle (anglais parlé).

Qu'est-ce que l'API Matcher?

La méthode ```est (attendue) `` `qui apparaissait dans le code source mentionné précédemment est Il s'agit d'une méthode statique implémentée dans la classe CoreMatcher de l'API Matcher. L'API Matcher est destinée aux assertions qui fournissent une ** méthode de comparaison de valeurs **. Il s'agit d'un mécanisme pour fournir une ** méthode de vérification de la valeur **, Auparavant, il était implémenté uniquement dans la bibliothèque d'extension JUnit appelée Hamcrest, Il est désormais également inclus dans JUnit lui-même.

Matcher fourni par Core Matchers

est "réel est attendu".

Vérifiez que les valeurs sont égales.

assertThat(actual, is(expected));

pas "réel n'est pas prévu."

Inversez le résultat de la vérification renvoyé par Matcher. Il peut également être appliqué aux Matchers autres que is.

assertThat(actual, is(not(expected)));

nullValue "réel est nul."

Étant donné que la méthode is a un paramètre de type, vous ne pouvez pas transmettre une valeur nulle. Par conséquent, si vous souhaitez effectuer une vérification null, utilisez la méthode nullValue.

assertThat(actual, is(nullValue()));
/* 
Le style d'écriture suivant est également possible,
Il est habituel d'écrire ce qui précède pour écrire plus comme un langage naturel.
*/
assertThat(actual, nullValue());

notNullValue "réel n'est pas nul."

Vérifiez que la valeur n'est pas nulle.

assertThat(actual, is(notNullValue()));
//Synonyme de
assertThat(actual, is(not(nullValue()));

sameInstance "réel et attendu sont la même instance."

Vérifiez que les valeurs sont égales. Alors que la méthode is compare par equals, sameInstance fait une comparaison par `` = relativement.

assertThat(actual, is(sameInstance(expected)));

instanceOf "actual est une valeur compatible avec attendue."

Vérifiez que la valeur hérite de la valeur attendue.

assertThat(actual, is(instanceOf(Serializable.class)));

Matcher fourni par JUnit Matchers

hasItem "réel contient attendu."

Pour les valeurs mesurées qui peuvent être répétées (avoir un itérateur) comme une classe de collection Vérifiez que la valeur attendue est incluse.

List<String> actual = getList();
assertThat(actual, hasItem(expected));

hasItems "réel contient attendu."

Le contenu à vérifier est le même que hasItem, sauf qu'il prend un argument de longueur variable pour la valeur supposée. Un Matcher utile pour vérifier que toutes les valeurs attendues sont incluses, quel que soit l'ordre.

List<String> actual = getList();
assertThat(actual, hasItem(expected1, expected2));

Supplément: Matcher fourni par hamcrest-library

Une autre bibliothèque d'extension appelée hamcrest-library Il fournit un Matcher qui peut être utilisé pour la vérification à usage général des collections, des nombres, des textes, etc. Il existe diverses autres bibliothèques d'extensions, donc avant d'introduire le Matcher personnalisé présenté ci-dessous, C'est une bonne idée de rechercher un Matcher qui est déjà disponible.

Matcher personnalisé

Matcher peut créer un Matcher personnalisé qui effectue sa propre validation. Ici, nous allons implémenter Matcher qui répond aux exigences suivantes.

・ Lors de la comparaison et de la vérification de la classe Date, l'année, le mois et le jour sont comparés. -Sortir la valeur supposée et la valeur mesurée dans le format suivant Format: est "Valeur supposée (aaaa / mm / jj)" mais réel est "Valeur réelle (aaaa / mm / jj)"

Voici l'implémentation de Matcher qui répond aux exigences ci-dessus et son traitement des appels.

DateTest.java


import static jp.sample.matcher.IsDate.*;
~réduction~
        assertThat(new Date(), is(dateOf(2020, 4, 12)));

IsDate.java


// 1.Déclaration de classe Matcher
public class IsDate extends BaseMatcher<Date> {

    // 3.Mise en place d'un mécanisme de maintien des valeurs supposées
    private final int yyyy;
    private final int mm;
    private final int dd;
    Object actual;

    // 3.Mise en place d'un mécanisme de maintien des valeurs supposées
    IsDate(int yyyy, int mm, int dd) {
        this.yyyy = yyyy;
        this.mm = mm;
        this.dd = dd;
    }

    // 4.Mise en œuvre du processus de vérification
    @Override
    public boolean matches(Object actual) {
        this.actual = actual;
        if (!(actual instanceof Date)) {
            return false;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime((Date) actual);
        if (yyyy != cal.get(Calendar.YEAR)) {
            return false;
        }
        if (mm != cal.get(Calendar.MONTH)) {
            return false;
        }
        if (dd != cal.get(Calendar.DATE)) {
            return false;
        }
        return true;
    }

    // 5.Implémentation du message d'erreur
    @Override
    public void describeTo(Description desc) {
        desc.appendValue(String.format("%d/%02d/%02d", yyyy, mm, dd));
        if (actual != null) {
            desc.appendText(" but actual is ");
            desc.appendValue(
                new SimpleDateFormat("yyyy/MM/dd").format((Date) actual));
        }
    }

    // 2.Mise en œuvre de la méthode de validation
    public static Matcher<Date> dateOf(int yyyy, int mm, int dd) {
        return new IsDate(yyyy, mm, dd);
    }
}

1. Déclaration de classe Matcher

L'interface org.hamcrest.Matcher comme classe d'implémentation pour Matcher personnalisé Implémenter, mais l'implémentation directe de l'interface Matcher est déconseillée. Nous implémentons donc l'interface Matcher Implémentez en héritant de org.hamcrest.BaseMatcher.

BaseMatcher a la valeur mesurée comme paramètre de type.

/* 
public class [Nom de classe arbitraire] extends BaseMatcher<[Type de valeur mesurée]> {
}
*/
public class IsDate extends BaseMatcher<Date> {
}

2. Mise en œuvre de la méthode de validation

Implémentez la méthode passée au deuxième argument de la méthode assertThat. La valeur supposée étant transmise au deuxième argument, définissez le constructeur de la classe Matcher. Initialisez la classe Matcher avec les valeurs attendues. Pour le mécanisme de maintien de la valeur supposée, reportez-vous à "3. Mise en œuvre du mécanisme de maintien de la valeur supposée".

/*
    public static Matcher<[Type de valeur mesurée]> [Nom de méthode arbitraire]([Valeurrequisepourl'initialisation]) {
        return [Constructeur de classe Matcher];
    }
*/
    public static Matcher<Date> dateOf(int yyyy, int mm, int dd) {
        return new IsDate(yyyy, mm, dd);
    }

3. Mise en œuvre d'un mécanisme de maintien des valeurs présumées

Les valeurs de mesure réelles et les valeurs supposées sont nécessaires pour vérifier les valeurs. Par conséquent, la classe Matcher implémente un mécanisme pour les conserver en tant que membres.

    //Membre détenant la valeur attendue
    private final int yyyy;
    private final int mm;
    private final int dd;
    //Membre tenant la valeur mesurée
    Object actual;

    //Constructeur pour définir la valeur attendue
    IsDate(int yyyy, int mm, int dd) {
        this.yyyy = yyyy;
        this.mm = mm;
        this.dd = dd;
    }

4. Mise en œuvre du processus de vérification

Lorsque la méthode assertThat est exécutée, elle est en cours de traitement La méthode matches définie dans l'interface Matcher est appelée. Si la valeur de retour est false dans la méthode matches, le test est jugé infructueux et s'il est vrai, le test est jugé réussi. Comme la valeur mesurée est prise comme argument, elle est vérifiée avec la valeur supposée détenue par la classe Matcher. Implémentez de sorte que true soit renvoyé si le résultat de la vérification est conforme aux attentes et false s'il est différent.

    @Override
    public boolean matches(Object actual) {
        //Conserver la valeur mesurée passée en tant que membre de la classe Matcher
        this.actual = actual;
        //Vérification de type(Ecrire promis)
        if (!(actual instanceof Date)) {
            return false;
        }
        //Ce qui suit est une implémentation originale, donc implémentez-la selon l'objectif
        Calendar cal = Calendar.getInstance();
        cal.setTime((Date) actual);
        if (yyyy != cal.get(Calendar.YEAR)) {
            return false;
        }
        if (mm != cal.get(Calendar.MONTH)) {
            return false;
        }
        if (dd != cal.get(Calendar.DATE)) {
            return false;
        }
        return true;
    }

5. Implémentation du message d'erreur

Comme la méthode matches, la méthode définie dans l'interface Matcher. Il est appelé uniquement lorsque le résultat du test échoue et que le message d'erreur est défini ici.

    @Override
    public void describeTo(Description desc) {
        //Sortie de valeur attendue
        desc.appendValue(String.format("%d/%02d/%02d", yyyy, mm, dd));
        //Sortie de la valeur mesurée
        if (actual != null) {
            desc.appendText(" but actual is ");
            desc.appendValue(
                new SimpleDateFormat("yyyy/MM/dd").format((Date) actual));
        }
    }

Résultat de sortie vers la console


java.lang.AssertionError:
Expected: is "2011/02/10" but actual is "2012/03/08"
     got: <Thu Mar 08 23:02:49 JST 2012>

Modèle de message d'erreur
[Nom de la classe d'erreur]
Expected: is [Message défini par la méthode describeTo]
     got: [Valeur mesurée au résultat de sortie de chaîne]

méthode appendValue

//Lorsqu'une chaîne de caractères est passée en argument
"2012/03/08" (Valeur entourée d'un double revêtement)
//Lorsqu'un objet est passé en argument
<Thu Mar 08 23:02:49 JST 2012> (Résultat de sortie ToString de l'objet passé)

méthode appendText

 but actual is  (Non entouré d'un double revêtement)

Les références

Cet article a été rédigé en référence aux informations suivantes.

Recommended Posts

Assertions JUnit et API Matcher
Tester l'API Web avec junit