Es wird behauptet, dass ein Objekt ein bestimmter Typ ist

195

Ist es in JUnit möglich zu behaupten, dass ein Objekt eine Instanz einer Klasse ist? Aus verschiedenen Gründen habe ich ein Objekt in meinem Test, dessen Typ ich überprüfen möchte. Ist es ein Typ von Objekt1 oder ein Typ von Objekt2?

Derzeit habe ich:

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

Das funktioniert, aber ich habe mich gefragt, ob es einen ausdrucksstärkeren Weg gibt, dies zu tun.

Zum Beispiel so etwas wie:

assertObjectIsClass(myObject, Object1);

Ich könnte das tun:

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

Gibt es eine bestimmte Assert-Methode, mit der ich einen Objekttyp eleganter und flüssiger testen kann?

RNJ
quelle
15
Ist dir das bewusst assertTrue(myObject instanceof Object1);und assertEquals(myObject.class, Object1.getClass());sind eigentlich verschiedene Tests? Der erste akzeptiert, dass myObject eine Instanz einer Unterklasse von ist Object1, der spätere nicht.
Erich Kitzmüller
@ammoQ Sehr guter Punkt. Ich habe nicht an Unterklassen gedacht. Vielen Dank für die Klarstellung
RNJ
1
Wie Maba betont, sollten Sie Hamcrest verwenden. Dies ist mehr als nur, damit Sie einen besseren Arbeitstest haben. Hamcrest bietet auch eine viel bessere Protokollierung des Fehlers als Standard assertTrue. assertTruewürde nur sagen expected true got false, Hamcrest würde sagenexpected instanced of XYZ, got instance of ABC
John B

Antworten:

253

Sie können die assertThatmit JUnit gelieferte Methode und die Matcher verwenden.

Schauen Sie sich diesen Link an , der ein wenig über die JUnit Matchers beschreibt.

Beispiel:

public class BaseClass {
}

public class SubClass extends BaseClass {
}

Prüfung:

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
quelle
4
Hier ist der Link zum verwendeten Matcher
John B
3
Zu Ihrer Information, MatcherAssert.assertThat verhält sich besser (bietet eine bessere Protokollierung bei Fehlern) als Assert.assertThat. Ich empfehle es stattdessen zu verwenden. hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/…
John B
13
Das ist eine triviale Behauptung und wäre ein Kompilierungsfehler, wenn dies im Beispiel nicht der Fall wäre! Normalerweise möchten Sie die Klassenhierarchie mit instanceof: durchgehen BaseClass subClass = new SubClass(); assertThat(subClass, isA(SubClass.class));, aber sie wird nicht kompiliert, weil dies nicht der Fall SubClassist ? super BaseClass.
TWiStErRob
3
@TWiStErRob Ich verstehe nicht, was Sie hier sagen wollen ... Versuchen Sie, das zu ändern instanceOf(BaseClass.class), instanceOf(String.class)und Sie werden sehen, dass es gut kompiliert wird, aber es wird ein AssertionError ausgelöst.
Maba
1
@maba, er spricht aus irgendeinem Grund von isA, das die Klasse erfasst, die es akzeptiert, Class<T>anstatt Class<?>(was instanceOf tut). Da es die Klasse erfasst, wäre es ein Fehler bei der Kompilierung, isA mit einer Klasse auszuführen, die mit der Instanz nicht kompatibel ist. github.com/hamcrest/JavaHamcrest/issues/39
Vsevolod Golovanov
46

Da assertThatdie alte Antwort jetzt veraltet ist, poste ich die richtige Lösung:

assertTrue(objectUnderTest instanceof TargetObject);

Carmageddon
quelle
2
Wenn objectUnderTest eine Unterklasse von TargetObject ist, führt dies immer noch zu truerichtig? Und ich denke, Sie möchten den tatsächlichen Typ testen.
EricG
Ich denke, das ist NICHT die richtige Antwort. Bei der ursprünglichen Frage wurde nach etwas gefragt, das speziell den genauen Typ des Objekts überprüft. Diese Lösung tut dies nicht (wie oben von @EircG erwähnt) und wurde sogar vom Benutzer bereitgestellt, der ursprünglich die Frage gestellt hat, also definitiv nicht die "richtige" Antwort imo. Die richtige Antwort finden Sie in der Franklin Yu-Antwort.
Kekko12
Nun, es hat den Nachteil, den @EricG mit Ja zu Franklins Antwort erwähnte - ich habe es mir nur angesehen und es ergab für mich keinen Sinn, also habe ich es gerade in meinem Projekt mit Junit5 getestet - es ist falsch !! Es gibt weder eine solche Syntax noch eine Methode namens InstanceOf! Er ist völlig falsch. Ich stehe immer noch zu meiner Antwort, und wie sich gezeigt hat, war es für mindestens 30 Personen hilfreich, die sie positiv bewertet haben! (Ich nehme an, Sie haben abgelehnt).
Carmageddon
@ kekko12 Meine Antwort überprüft auch nicht den genauen Typ; Es akzeptiert eine ähnliche Unterklasse wie diese Antwort. Ich habe meine Antwort aktualisiert, um sie zu adressieren. Entschuldigung, dass ich diesen fraglichen Teil nicht bemerkt habe. Ich denke, dass exakte Gleichheit in den meisten Assertionsbibliotheken nicht enthalten ist, da sie nicht häufig verwendet wird.
Franklin Yu
@Carmageddon Die Antwort von Franlin Yu funktioniert einwandfrei, wenn Sie den Import von Hamcrest-Assertions verwenden: `` `statische org.hamcrest.CoreMatchers.instanceOf importieren; `` `ss nach seinen Codebeispielen. Ich gebe zu, obwohl ich bei Franklin die Antwort übersehen habe, und tatsächlich sind diese beiden Antworten funktional gleichwertig, also denke ich, dass es am Ende nur eine Frage der Präferenz ist.
Kekko12
21

Lösung für JUnit 5

Die Dokumentation sagt:

Die org.junit.jupiter.AssertionsKlasse von JUnit Jupiter bietet jedoch keine assertThat()Methode wie die in der org.junit.AssertKlasse von JUnit 4, die ein Hamcrest akzeptiert Matcher. Stattdessen wird Entwicklern empfohlen, die integrierte Unterstützung für Matcher zu verwenden, die von Assertion-Bibliotheken von Drittanbietern bereitgestellt werden.

Beispiel für 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));
    }

}

Beispiel für 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);
    }

}

Beachten Sie, dass dies voraussetzt, dass Sie ähnliche Verhaltensweisen testen möchten instanceof(die Unterklassen akzeptieren). Wenn Sie einen exakt gleichen Typ wünschen, sehe ich keinen besseren Weg, als zu behaupten, dass die beiden Klassen gleich sind, wie Sie in der Frage erwähnt haben.

Franklin Yu
quelle
1
In gewisser Weise wird das Original assertThat()auf Hamcrest verschoben, sodass JUnit auch mit Assertion-Bibliotheken von Drittanbietern zusammenarbeitet.
Franklin Yu
Ich habe diese Antwort gerade getestet, sie ist NICHT korrekt und führt zu mehreren Kompilierungsfehlern: Unzulässiger Beginn des Ausdrucks, unzulässiger Beginn des Typs, ';' erwartet ... Mit anderen Worten, Ihr zweiter Parameter für den assertThat-Matcher kann NICHT "instanceof (BaseClass.class)" sein! Tatsächlich haben Sie das nicht einmal richtig eingegeben, die von Ihnen verwendete Syntax unterscheidet sich geringfügig - "InstanceOf (" - als Funktionsaufruf! Es gibt tatsächlich keine solche Funktion ... wurde sie überhaupt von jemandem getestet? Sie scheint manuell gewesen zu sein ohne Tests getippt
Carmageddon
@ Carmageddon Ich gab zwei Antworten, eine für Hamcrest und die andere für AssertJ. Von welchem ​​sprichst du?
Franklin Yu
@Carmageddon Ich vermute , dass Sie das hamcrest Beispiel sprechen und Sie verpassen typisierte instanceOfwie instanceof(den Fall dagegen). instanceOfist eine Funktion, während instanceofes sich um ein Java-Schlüsselwort handelt .
Franklin Yu
Ich habe mich natürlich auf das Hamcrest bezogen und beide Schlüsselwörter UND als Funktion ausprobiert, nachdem ich bemerkt habe, dass Sie es so geschrieben haben - es gibt keine solche Funktion ...
Carmageddon
3

Lösung für JUnit 5 für Kotlin!

Beispiel für 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))
    }

}

Beispiel für 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
quelle
1
Vielen Dank für diese sehr elegante Lösung
Aleks Nine