Affirmer qu'un objet est un type spécifique

195

Est-il possible dans JUnit d'affirmer qu'un objet est une instance d'une classe? Pour diverses raisons, j'ai un objet dans mon test dont je souhaite vérifier le type. S'agit-il d'un type d'Object1 ou d'un type d'Object2?

Actuellement j'ai:

assertTrue(myObject instanceof Object1);
assertTrue(myObject instanceof Object2);

Cela fonctionne mais je me demandais s'il existe une manière plus expressive de le faire.

Par exemple quelque chose comme:

assertObjectIsClass(myObject, Object1);

Je pourrais faire ceci:

assertEquals(myObject.class, Object1.getClass());

Existe-t-il une méthode d'assert spécifique qui me permet de tester un type d'objet de manière plus élégante et fluide?

RNJ
la source
15
Êtes-vous conscient de cela assertTrue(myObject instanceof Object1);et assertEquals(myObject.class, Object1.getClass());sont en fait des tests différents? Le premier accepte que myObject soit une instance d'une sous-classe de Object1, le second ne le fait pas.
Erich Kitzmueller
@ammoQ Très bon point. Je n'ai pas pensé aux sous-classes. Merci pour la clarifaction
RNJ
1
comme le souligne maba, pensez à utiliser Hamcrest. C'est plus que juste pour que vous ayez un meilleur test de fonctionnement. Hamcrest fournit également une meilleure journalisation de l'échec que la norme assertTrue. assertTruedirait juste, dirait expected true got falseHamcrestexpected instanced of XYZ, got instance of ABC
John B

Réponses:

253

Vous pouvez utiliser la assertThatméthode et les Matchers fournis avec JUnit.

Jetez un œil à ce lien qui décrit un peu plus les JUnit Matchers.

Exemple:

public class BaseClass {
}

public class SubClass extends BaseClass {
}

Tester:

import org.junit.Test;

import static org.hamcrest.CoreMatchers.instanceOf;
import static org.junit.Assert.assertThat;

/**
 * @author maba, 2012-09-13
 */
public class InstanceOfTest {

    @Test
    public void testInstanceOf() {
        SubClass subClass = new SubClass();
        assertThat(subClass, instanceOf(BaseClass.class));
    }
}
maba
la source
4
Voici le lien vers le Matcher
John B
3
FYI, MatcherAssert.assert qui se comporte mieux (fournit une meilleure journalisation en cas d'erreurs) que Assert.assertThat. Je recommande de l'utiliser à la place. hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/…
John B
13
C'est une assertion triviale et ce serait une erreur de compilation si ce n'est pas vrai dans l'exemple! Habituellement , vous voulez aller dans la hiérarchie des classes avec instanceof: BaseClass subClass = new SubClass(); assertThat(subClass, isA(SubClass.class));, mais il ne compile pas parce que SubClassn'est pas ? super BaseClass.
TWiStErRob
3
@TWiStErRob Je ne comprends pas ce que vous essayez de dire ici ... Essayez de changer le instanceOf(BaseClass.class)en instanceOf(String.class)et vous verrez qu'il compile très bien mais il y aura une AssertionError lancée.
maba
1
@maba, il parle de isA pour une raison quelconque, qui capture la classe, il accepte à la Class<T>place de Class<?>(ce que fait instanceOf). Puisqu'il capture la classe, ce serait une erreur de compilation de faire isA avec une classe incompatible avec l'instance. github.com/hamcrest/JavaHamcrest/issues/39
Vsevolod Golovanov
47

Depuis assertThatquelle était l'ancienne réponse est maintenant obsolète, je publie la bonne solution:

assertTrue(objectUnderTest instanceof TargetObject);

Carmageddon
la source
2
si objectUnderTest est une sous-classe de TargetObject, cela se traduira toujours par un truedroit? Et je pense que vous voulez tester le type réel.
EricG
Je pense que ce n'est PAS la bonne réponse. La question originale demandait quelque chose qui vérifie spécifiquement le type exact de l'objet. Cette solution ne fait pas ça (comme mentionné par @EircG ci-dessus) et elle a même été fournie par l'utilisateur qui a posé la question à l'origine, donc certainement pas la «bonne» réponse imo. Pour la bonne réponse, veuillez vérifier la réponse de Franklin Yu.
kekko12
Eh bien, cela a l'inconvénient que @EricG a mentionné oui, à propos de la réponse de Franklin - je l'ai juste regardée, et cela n'avait pas de sens pour moi alors j'ai juste testé dans mon projet avec Junit5 - c'est faux !! il n'y a pas de telle syntaxe pour instanceof, ni une méthode appelée InstanceOf! Il a totalement tort. Je reste fidèle à ma réponse et, comme en témoigne, cela a été utile à au moins 30 personnes qui l'ont votée! (Je suppose que vous avez voté contre).
Carmageddon
@ kekko12 Ma réponse ne vérifie pas non plus le type exact; il accepte une sous-classe similaire à cette réponse. J'ai mis à jour ma réponse pour y remédier; désolé de ne pas avoir remarqué cette partie en question. Je pense que l'égalité exacte n'est pas incluse dans la plupart des bibliothèques d'assertions car elle n'est pas fréquemment utilisée.
Franklin Yu
@Carmageddon La réponse de Franlin Yu fonctionne bien si vous utilisez l'importation d'assertions hamcrest: `` import static org.hamcrest.CoreMatchers.instanceOf; `` ss par ses échantillons de code. J'admets bien que j'ai négligé la réponse de Franklin et qu'en fait, ces 2 réponses sont fonctionnellement équivalentes, donc je suppose que c'est juste une question de préférence à la fin.
kekko12
23

Solution pour JUnit 5

La documentation dit:

Cependant, la org.junit.jupiter.Assertionsclasse de JUnit Jupiter ne fournit pas de assertThat()méthode comme celle trouvée dans la org.junit.Assertclasse de JUnit 4 qui accepte un Hamcrest Matcher. Au lieu de cela, les développeurs sont encouragés à utiliser la prise en charge intégrée des correspondances fournie par des bibliothèques d'assertions tierces.

Exemple pour Hamcrest :

import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.MatcherAssert.assertThat;

import org.junit.jupiter.api.Test;

class HamcrestAssertionDemo {

    @Test
    void assertWithHamcrestMatcher() {
        SubClass subClass = new SubClass();
        assertThat(subClass, instanceOf(BaseClass.class));
    }

}

Exemple pour AssertJ :

import static org.assertj.core.api.Assertions.assertThat;

import org.junit.jupiter.api.Test;

class AssertJDemo {

    @Test
    void assertWithAssertJ() {
        SubClass subClass = new SubClass();
        assertThat(subClass).isInstanceOf(BaseClass.class);
    }

}

Notez que cela suppose que vous souhaitiez tester des comportements similaires à instanceof(qui accepte les sous-classes). Si vous voulez un type égal exact, je ne vois pas de meilleur moyen que d'affirmer que les deux classes sont égales comme vous l'avez mentionné dans la question.

Franklin Yu
la source
1
Dans un sens, l'original assertThat()est reporté à Hamcrest, de sorte que JUnit fonctionne également avec des bibliothèques d'assertions tierces.
Franklin Yu
Je viens de tester cette réponse, elle n'est PAS correcte et conduit à de multiples erreurs de compilation: début d'expression illégal, début de type illégal, ';' attendu ... En d'autres termes, votre deuxième paramètre de l'assertThat matcher, NE PEUT PAS être "instanceof (BaseClass.class)"! En fait, vous ne l'avez même pas tapé correctement, la syntaxe que vous avez utilisée est légèrement différente - "InstanceOf (" - en tant qu'appel de fonction! Il n'y a pas de fonction de ce type en fait ... a-t-elle même été testée par quelqu'un? Cela semble avoir été manuellement tapé sans aucun test
Carmageddon
@Carmageddon J'ai fourni deux réponses, une pour Hamcrest et l'autre pour AssertJ. De laquelle parlez-vous?
Franklin Yu
@Carmageddon Je soupçonne que vous parlez de l'exemple Hamcrest et que vous avez mal tapé instanceOfcomme instanceof(attention au cas). instanceOfest une fonction tandis que instanceofest un mot-clé Java .
Franklin Yu
J'ai fait référence au Hamcrest bien sûr, et j'ai essayé à la fois le mot-clé ET en tant que fonction après avoir remarqué que c'est comme ça que vous l'avez écrit - il n'y a pas de telle fonction ...
Carmageddon
3

Solution pour JUnit 5 pour Kotlin!

Exemple pour Hamcrest :

import org.hamcrest.CoreMatchers
import org.hamcrest.MatcherAssert
import org.junit.jupiter.api.Test

class HamcrestAssertionDemo {

    @Test
    fun assertWithHamcrestMatcher() {
        val subClass = SubClass()
        MatcherAssert.assertThat(subClass, CoreMatchers.instanceOf<Any>(BaseClass::class.java))
    }

}

Exemple pour AssertJ :

import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test

class AssertJDemo {

    @Test
    fun assertWithAssertJ() {
        val subClass = SubClass()
        assertThat(subClass).isInstanceOf(BaseClass::class.java)
    }

}
Naruto Sempai
la source
1
Merci pour cette solution assertJ très élégante
Aleks Nine