Menyatakan objek adalah tipe tertentu

195

Apakah mungkin di JUnit untuk menegaskan suatu objek adalah turunan dari kelas? Karena berbagai alasan, saya memiliki objek dalam pengujian yang ingin saya periksa jenisnya. Apakah itu tipe Object1 atau tipe Object2?

Saat ini saya punya:

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

Ini bekerja tetapi saya bertanya-tanya apakah ada cara yang lebih ekspresif untuk melakukan ini.

Misalnya sesuatu seperti:

assertObjectIsClass(myObject, Object1);

Saya bisa melakukan ini:

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

Apakah ada metode penegasan khusus yang memungkinkan saya untuk menguji jenis objek dengan cara yang lebih elegan dan lancar?

RNJ
sumber
15
Apakah Anda menyadari itu assertTrue(myObject instanceof Object1);dan assertEquals(myObject.class, Object1.getClass());sebenarnya tes yang berbeda? Yang pertama menerima myObject menjadi turunan dari subclass Object1, yang kemudian tidak.
Erich Kitzmueller
@ammoQ Poin yang sangat bagus. Saya tidak memikirkan subclass. Terima kasih atas klarifikasi
RNJ
1
sebagaimana ditunjukkan maba, pertimbangkan untuk menggunakan Hamcrest. Ini lebih dari sekadar agar Anda memiliki tes kerja yang lebih baik. Hamcrest juga menyediakan logging kegagalan yang jauh lebih baik daripada standar assertTrue. assertTruehanya akan mengatakan expected true got false, Hamcrest akan mengatakanexpected instanced of XYZ, got instance of ABC
John B

Jawaban:

253

Anda dapat menggunakan assertThatmetode dan Pencocokan yang datang dengan JUnit.

Lihatlah tautan ini yang menjelaskan sedikit tentang JUnit Matchers.

Contoh:

public class BaseClass {
}

public class SubClass extends BaseClass {
}

Uji:

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
sumber
4
Berikut adalah tautan ke Pencocokan yang digunakan: hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/…
John B
3
FYI, MatcherAssert.assertThat berperilaku lebih baik (memberikan pencatatan yang lebih baik jika terjadi kesalahan) daripada Assert.assertThat. Saya sarankan menggunakannya sebagai gantinya. hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/…
John B
13
Itu pernyataan sepele dan akan menjadi kesalahan kompilasi jika tidak benar dalam contoh! Biasanya Anda ingin turun hirarki kelas dengan instanceof: BaseClass subClass = new SubClass(); assertThat(subClass, isA(SubClass.class));, tetapi tidak mengkompilasi karena SubClasstidak ? super BaseClass.
TWiStErRob
3
@TWiStErRob Saya tidak mengerti apa yang ingin Anda katakan di sini ... Cobalah untuk mengubah instanceOf(BaseClass.class)ke instanceOf(String.class)dan Anda akan melihat bahwa itu mengkompilasi dengan baik tetapi akan ada AssertionError dilemparkan.
maba
1
@ maba, dia berbicara tentang isA untuk beberapa alasan, yang menangkap kelas, ia menerima Class<T>alih-alih Class<?>(yang dilakukan oleh instanceOf). Karena ia menangkap kelas, itu akan menjadi kesalahan waktu kompilasi untuk melakukan isA dengan kelas yang tidak kompatibel dengan instance. github.com/hamcrest/JavaHamcrest/issues/39
Vsevolod Golovanov
46

Karena assertThatyang dulu jawabannya sudah usang, saya memposting solusi yang benar:

assertTrue(objectUnderTest instanceof TargetObject);

Carmageddon
sumber
2
jika objectUnderTest adalah subkelas dari TargetObject, ini masih akan menghasilkan truebenar? Dan saya pikir Anda ingin menguji tipe yang sebenarnya.
EricG
Saya merasa ini BUKAN jawaban yang benar. Pertanyaan aslinya adalah menanyakan sesuatu yang secara khusus memeriksa jenis objek yang tepat. Solusi ini tidak seperti itu (seperti yang disebutkan oleh @EircG di atas) dan bahkan telah disediakan oleh pengguna yang pada awalnya mengajukan pertanyaan, jadi jelas bukan jawaban "benar". Untuk jawaban yang benar, silakan periksa jawaban Franklin Yu.
kekko12
Yah, ini memiliki kelemahan yang @EricG sebutkan ya, tentang jawaban Franklin - Saya baru saja melihatnya, dan itu tidak masuk akal bagi saya jadi saya baru saja menguji proyek saya dengan Junit5 - itu salah !! tidak ada sintaks seperti untuk instanceof, atau metode yang disebut InstanceOf! Dia benar-benar salah. Saya tetap berdiri dengan jawaban saya, dan terbukti, itu membantu setidaknya 30 orang yang mengangkatnya! (Saya menganggap Anda downvoted).
Carmageddon
@ kekko12 Jawaban saya tidak memeriksa jenis yang tepat juga; menerima subkelas yang mirip dengan jawaban ini. Saya telah memperbarui jawaban saya untuk mengatasinya; maaf saya tidak memperhatikan bagian ini. Saya pikir kesetaraan yang tepat tidak termasuk dalam sebagian besar perpustakaan pernyataan karena itu tidak sering digunakan.
Franklin Yu
@Carmageddon Jawaban dari Franlin Yu tidak berfungsi dengan baik jika Anda menggunakan pernyataan hamcrest mengimpor: `` `import static org.hamcrest.CoreMatchers.instanceOf; `s` per sampel kode-nya. Saya mengakui meskipun saya mengabaikan jawaban Franklin dan pada kenyataannya, 2 jawaban ini secara fungsional setara, jadi saya kira itu hanya masalah preferensi pada akhirnya.
kekko12
21

Solusi untuk JUnit 5

Dokumentasi mengatakan:

Namun, org.junit.jupiter.Assertionskelas JUnit Jupiter tidak menyediakan assertThat()metode seperti yang ditemukan di org.junit.Assertkelas JUnit 4 yang menerima Hamcrest Matcher. Sebaliknya, pengembang didorong untuk menggunakan dukungan bawaan untuk pencocokan yang disediakan oleh perpustakaan pernyataan pihak ketiga.

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

}

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

}

Perhatikan bahwa ini mengasumsikan Anda ingin menguji perilaku yang mirip dengan instanceof(yang menerima subkelas). Jika Anda ingin tipe yang sama persis, saya tidak melihat cara yang lebih baik daripada menyatakan bahwa dua kelas sama dengan yang Anda sebutkan dalam pertanyaan.

Franklin Yu
sumber
1
Dalam arti tertentu, dokumen asli assertThat()ditangguhkan ke Hamcrest, sehingga JUnit juga bekerja dengan perpustakaan pernyataan pihak ketiga.
Franklin Yu
Saya baru saja menguji jawaban ini, BUKAN benar dan mengarah ke beberapa kesalahan kompilasi: Awal ekspresi tidak sah, jenis awal ilegal, ';' diharapkan ... Dengan kata lain, parameter kedua Anda ke pencocokan assertThat itu, TIDAK BISA menjadi "instanceof (BaseClass.class)"! Bahkan, Anda bahkan tidak mengetik dengan benar, sintaks yang Anda gunakan sedikit berbeda - "InstanceOf (" - sebagai panggilan fungsi! Sebenarnya tidak ada fungsi seperti itu ... apakah itu bahkan diuji oleh siapa pun? Tampaknya telah secara manual diketik tanpa tes apa pun
Carmageddon
@Carmageddon Saya memberikan dua jawaban, satu untuk Hamcrest dan yang lainnya untuk AssertJ. Yang mana yang kamu bicarakan?
Franklin Yu
@Carmageddon Saya menduga bahwa Anda berbicara tentang contoh Hamcrest dan Anda kehilangan diketik instanceOfsebagai instanceof(keberatan kasus). instanceOfadalah fungsi sementara instanceofadalah kata kunci Java .
Franklin Yu
Saya merujuk ke Hamcrest salah satu saja, dan saya mencoba kedua kata kunci DAN sebagai fungsi setelah saya perhatikan itulah bagaimana Anda menulisnya - tidak ada fungsi seperti itu ...
Carmageddon
3

Solusi untuk JUnit 5 untuk Kotlin!

Contoh untuk 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))
    }

}

Contoh untuk 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
sumber
1
Terima kasih atas solusi yang sangat elegan ini
Aleks Nine