Asserire che un oggetto è un tipo specifico


195

È possibile in JUnit affermare che un oggetto è un'istanza di una classe? Per vari motivi ho un oggetto nel mio test di cui voglio verificare il tipo. È un tipo di Object1 o un tipo di Object2?

Attualmente ho:

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

Funziona ma mi chiedevo se esiste un modo più espressivo per farlo.

Ad esempio qualcosa del tipo:

assertObjectIsClass(myObject, Object1);

Potrei farlo:

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

Esiste un metodo di asserzione specifico che mi consente di testare un tipo di oggetto in un modo più elegante e fluido?


15
Ne sei consapevole assertTrue(myObject instanceof Object1);e in assertEquals(myObject.class, Object1.getClass());realtà sono test diversi? Il primo accetta myObject come istanza di una sottoclasse di Object1, il successivo no.
Erich Kitzmueller,

@ammoQ Ottimo punto. Non pensavo alle sottoclassi. Grazie per il chiarimento
RNJ

1
come sottolinea maba, considera l'utilizzo di Hamcrest. Questo è molto più che solo per avere un test di lavoro migliore. Hamcrest fornisce inoltre una registrazione degli errori molto migliore rispetto allo standard assertTrue. assertTruedirei semplicemente expected true got false, Hamcrest direbbeexpected instanced of XYZ, got instance of ABC
John B,

Risposte:


253

È possibile utilizzare il assertThatmetodo e i Matcher forniti con JUnit.

Dai un'occhiata a questo link che descrive un po 'di JUnit Matchers.

Esempio:

public class BaseClass {
}

public class SubClass extends BaseClass {
}

Test:

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));
    }
}


3
Cordiali saluti, MatcherAssert.assert Che si comporta meglio (fornisce una migliore registrazione in caso di errori) rispetto ad Assert.assertThat. Consiglio invece di usarlo. hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/…
John B

13
Questa è una banale affermazione e sarebbe un errore di compilazione se non fosse vero nell'esempio! Di solito si vuole andare giù per la gerarchia di classe con instanceof: BaseClass subClass = new SubClass(); assertThat(subClass, isA(SubClass.class));, ma non viene compilato perché SubClassnon è ? super BaseClass.
TWiStErRob,

3
@TWiStErRob Non capisco cosa stai cercando di dire qui ... Prova a cambiare instanceOf(BaseClass.class)in instanceOf(String.class)e vedrai che si compila bene, ma verrà lanciato un AssertionError.
maba

1
@maba, sta parlando di isA per qualche motivo, che cattura la classe, accetta Class<T>invece Class<?>(che è ciò che fa InstanceF ). Dato che cattura la classe, sarebbe un errore di compilazione fare isA con una classe incompatibile con l'istanza. github.com/hamcrest/JavaHamcrest/issues/39
Vsevolod Golovanov

47

Dal momento assertThatche la vecchia risposta è ora obsoleta, sto pubblicando la soluzione corretta:

assertTrue(objectUnderTest instanceof TargetObject);


2
se objectUnderTest è una sottoclasse di TargetObject, questo risulterà comunque truecorretto? E penso che tu voglia testare il tipo reale.
EricG,

Sento che questa NON è la risposta corretta. La domanda originale era chiedere qualcosa che controlla specificamente il tipo esatto dell'oggetto. Questa soluzione non lo fa (come menzionato da @EircG sopra) ed è stata persino fornita dall'utente originariamente ponendo la domanda, quindi sicuramente non la risposta "corretta" imo. Per la risposta corretta, controlla la risposta di Franklin Yu.
kekko12,

Bene, ha il rovescio della medaglia che @EricG ha menzionato sì, sulla risposta di Franklin - l'ho appena guardato, e non aveva senso per me, quindi ho appena testato nel mio progetto con Junit5 - è sbagliato !! non esiste una sintassi simile per esempio di né un metodo chiamato InstanceOf! Ha totalmente torto. Attendo ancora la mia risposta e, come dimostrato, è stato utile per almeno 30 persone che l'hanno votata! (Presumo che tu abbia effettuato il downgrade).
Carmageddon,

@ kekko12 La mia risposta non controlla nemmeno il tipo esatto; accetta sottoclassi simili a questa risposta. Ho aggiornato la mia risposta per affrontarla; mi dispiace di non aver notato questa parte in questione. Penso che l'uguaglianza esatta non sia inclusa nella maggior parte delle librerie di asserzioni perché non viene usata frequentemente.
Franklin Yu,

@Carmageddon La risposta di Franlin Yu funziona benissimo se usi l'importazione delle affermazioni più ambiziose: `` import static org.hamcrest.CoreMatchers.instanceOf; `` ss per i suoi esempi di codice. Lo ammetto anche se ho trascurato la risposta di Franklin e in effetti, queste 2 risposte sono funzionalmente equivalenti, quindi immagino che alla fine sia solo una questione di preferenza.
kekko12,

23

Soluzione per JUnit 5

La documentazione dice:

Tuttavia, la org.junit.jupiter.Assertionsclasse di JUnit Jupiter non fornisce un assertThat()metodo come quello trovato nella org.junit.Assertclasse di JUnit 4 che accetta un Hamcrest Matcher. Al contrario, gli sviluppatori sono incoraggiati a utilizzare il supporto integrato per i matcher fornito da librerie di asserzioni di terze parti.

Esempio per 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));
    }

}

Esempio per 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);
    }

}

Si noti che ciò presuppone che si desidera testare comportamenti simili a instanceof(che accetta le sottoclassi). Se vuoi il tipo esatto uguale, non vedo un modo migliore che affermare che le due classi siano uguali come hai menzionato nella domanda.


1
In un certo senso, l'originale assertThat()viene rinviato a Hamcrest, in modo che JUnit funzioni anche con librerie di asserzioni di terze parti.
Franklin Yu,

Ho appena testato questa risposta, NON è corretta e porta a più errori di compilazione: inizio di espressione illegale, inizio di tipo illegale, ';' previsto ... In altre parole, il tuo secondo parametro per l'assertThat matcher, NON PU be essere "instanceof (BaseClass.class)"! In effetti, non hai nemmeno digitato correttamente quella, la sintassi che hai usato è leggermente diversa - "InstanceOf (" - come una chiamata di funzione! In realtà non esiste una tale funzione ... è stata testata da nessuno? Sembra che sia stata manualmente digitato senza prove
Carmageddon,

@Carmageddon Ho fornito due risposte, una per Hamcrest e l'altra per AssertJ. Di quale stai parlando?
Franklin Yu,

@Carmageddon Sospetto che tu stia parlando dell'esempio di Hamcrest e che tu abbia sbagliato a scrivere instanceOfcome instanceof(attenzione al caso). instanceOfè una funzione mentre lo instanceofè una parola chiave Java .
Franklin Yu,

Ho fatto riferimento all'Hamcrest ovviamente, e ho provato entrambe le parole chiave E come funzione dopo aver notato che è così che l'hai scritto - non esiste tale funzione ...
Carmageddon

3

Soluzione per JUnit 5 per Kotlin!

Esempio per 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))
    }

}

Esempio per 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)
    }

}

1
Grazie per questa soluzione assertJ molto elegante
Aleks Nine,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.