ยืนยันวัตถุเป็นประเภทที่เฉพาะเจาะจง


195

เป็นไปได้ใน JUnit เพื่อยืนยันวัตถุเป็นตัวอย่างของชั้น? ด้วยเหตุผลหลายประการฉันมีวัตถุในการทดสอบของฉันที่ฉันต้องการตรวจสอบประเภทของ มันเป็นประเภทของ Object1 หรือชนิดของ Object2 หรือไม่?

ปัจจุบันฉันมี:

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

ใช้งานได้ แต่ฉันสงสัยว่ามีวิธีที่แสดงออกมากขึ้นในการทำเช่นนี้

ตัวอย่างเช่น:

assertObjectIsClass(myObject, Object1);

ฉันสามารถทำสิ่งนี้:

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

มีวิธีการยืนยันที่เฉพาะเจาะจงที่อนุญาตให้ฉันทดสอบวัตถุชนิดใดแบบหนึ่งที่ดูสง่างามกว่า


15
คุณรู้หรือไม่ว่าassertTrue(myObject instanceof Object1);และassertEquals(myObject.class, Object1.getClass());มีการทดสอบที่แตกต่างกันจริง ๆ ? ครั้งแรกที่ยอมรับ myObject เป็นตัวอย่างของคลาสย่อยของObject1ในภายหลังไม่
Erich Kitzmueller

@ammoQ เป็นจุดที่ดีมาก ฉันไม่คิดว่า subclasses ขอบคุณสำหรับ clarifaction
RNJ

1
ดังที่ maba ระบุให้ใช้ Hamcrest นี่เป็นมากกว่าเพียงแค่การทดสอบการทำงานที่ดีขึ้น Hamcrest ยังให้การบันทึกความล้มเหลวได้ดีกว่ามาตรฐานassertTrueมาก assertTrueจะบอกว่าexpected true got falseHamcrest จะพูดexpected instanced of XYZ, got instance of ABC
John B

คำตอบ:


253

คุณสามารถใช้assertThatวิธีการและตัวจับคู่ที่มาพร้อมกับ JUnit

ลองดูที่ลิงค์นี้ซึ่งอธิบายเล็กน้อยเกี่ยวกับ JUnit Matchers

ตัวอย่าง:

public class BaseClass {
}

public class SubClass extends BaseClass {
}

ทดสอบ:

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

4
นี่คือลิงค์ไปยัง Matcher ที่ใช้: hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/ …
John B

3
FYI, MatcherAssert.assert ว่าทำงานได้ดีกว่า (ให้การบันทึกที่ดีกว่าในกรณีที่เกิดข้อผิดพลาด) กว่า Assert.assert ฉันแนะนำให้ใช้มันแทน hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/ …
John B

13
นั่นเป็นการยืนยันเล็กน้อยและจะเป็นข้อผิดพลาดในการคอมไพล์หากไม่เป็นจริงในตัวอย่าง! โดยปกติแล้วคุณต้องการที่จะไปลงลำดับชั้นด้วยinstanceof: BaseClass subClass = new SubClass(); assertThat(subClass, isA(SubClass.class));แต่มันก็ไม่ได้รวบรวมเพราะไม่ได้เป็นSubClass ? super BaseClass
TWiStErRob

3
@TWiStErRob ฉันไม่เข้าใจสิ่งที่คุณกำลังพยายามที่จะบอกว่าที่นี่ ... พยายามที่จะเปลี่ยนinstanceOf(BaseClass.class)ไปinstanceOf(String.class)และคุณจะเห็นว่ามันรวบรวมปรับเพียง แต่จะมีการโยน AssertionError
maba

1
@maba เขากำลังพูดถึง isA ด้วยเหตุผลบางอย่างซึ่งจับชั้นเรียนมันยอมรับClass<T>แทนClass<?>(ซึ่งเป็นสิ่งที่ instanceOf ทำ) เนื่องจากมันจับคลาสมันจะเป็นข้อผิดพลาดในการคอมไพล์เวลาในการทำ isA กับคลาสที่เข้ากันไม่ได้กับอินสแตนซ์ github.com/hamcrest/JavaHamcrest/issues/39
Vsevolod Golovanov

46

เนื่องจากassertThatคำตอบเดิมนั้นเลิกใช้แล้วฉันกำลังโพสต์โซลูชันที่ถูกต้อง:

assertTrue(objectUnderTest instanceof TargetObject);


2
ถ้า objectUnderTest เป็น subclass ของ TargetObject สิ่งนี้จะยังคงมีผลtrueใช่ไหม? และฉันคิดว่าคุณต้องการทดสอบประเภทจริง
EricG

ฉันรู้สึกว่านี่ไม่ใช่คำตอบที่ถูกต้อง คำถามเดิมกำลังถามหาสิ่งที่ตรวจสอบชนิดของวัตถุที่แน่นอน การแก้ปัญหานี้ไม่ได้เป็นเช่นนั้น (ดังที่ได้รับการกล่าวถึงโดย @EircG ด้านบน) และได้รับการจัดเตรียมโดยผู้ใช้ในตอนแรกที่ถามคำถามดังนั้นจึงไม่ใช่คำตอบ "ถูกต้อง" สำหรับคำตอบที่ถูกต้องโปรดตรวจสอบคำตอบของ Franklin Yu
kekko12

มันมีข้อเสียที่ @EricG พูดถึงใช่เกี่ยวกับคำตอบของแฟรงคลิน - ฉันแค่ดูมันและมันก็ไม่สมเหตุสมผลสำหรับฉันดังนั้นฉันเพิ่งทดสอบโครงการของฉันกับ Junit5 - มันผิด !! ไม่มีไวยากรณ์ดังกล่าวสำหรับอินสแตนซ์ของหรือวิธีการที่เรียกว่า InstanceOf! เขาผิดทั้งหมด ฉันยืนตามคำตอบของฉันและเป็นหลักฐานมันเป็นประโยชน์อย่างน้อย 30 คนที่ upvoted มัน! (ฉันคิดว่าคุณลงคะแนน)
Carmageddon

@ kekko12 คำตอบของฉันไม่ได้ตรวจสอบประเภทที่แน่นอนเช่นกัน; ยอมรับคลาสย่อยที่คล้ายกับคำตอบนี้ ฉันได้อัปเดตคำตอบเพื่อแก้ไขแล้ว ขออภัยที่ฉันไม่ได้สังเกตเห็นส่วนนี้ในคำถาม ฉันคิดว่าความเท่าเทียมที่แน่นอนไม่รวมอยู่ในห้องสมุดยืนยันส่วนใหญ่เพราะไม่ได้ใช้บ่อย
Franklin Yu

@Cagageddon คำตอบจาก Franlin Yu ทำงานได้ดีถ้าคุณใช้การยืนยันการนำเข้า hamcrest: `` `นำเข้าคงที่ org.hamcrest.CoreMatchers.instanceOf; `` `ss ต่อตัวอย่างรหัสของเขา ฉันยอมรับแม้ว่าฉันจะมองข้ามคำตอบของแฟรงคลิน แต่อันที่จริงคำตอบ 2 ข้อเหล่านี้มีหน้าที่เทียบเท่าดังนั้นฉันคิดว่ามันเป็นเรื่องของความพึงพอใจในท้ายที่สุด
kekko12

23

โซลูชันสำหรับ JUnit 5

เอกสารกล่าวว่า:

อย่างไรก็ตาม JUnit ดาวพฤหัสบดีorg.junit.jupiter.Assertionsชั้นไม่ได้ให้assertThat()วิธีการอย่างหนึ่งที่พบใน JUnit 4 org.junit.Assertระดับซึ่งยอมรับ MatcherHamcrest แต่ผู้พัฒนาได้รับการสนับสนุนให้ใช้การสนับสนุนในตัวสำหรับ matchers ที่จัดหาโดยไลบรารียืนยันของบุคคลที่สาม

ตัวอย่างสำหรับ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));
    }

}

ตัวอย่างสำหรับ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);
    }

}

โปรดทราบว่าสิ่งนี้ถือว่าคุณต้องการทดสอบพฤติกรรมที่คล้ายคลึงกับinstanceof(ซึ่งยอมรับคลาสย่อย) หากคุณต้องการประเภทที่เท่าเทียมกันแน่นอนฉันไม่เห็นวิธีที่ดีไปกว่าการยืนยันทั้งสองคลาสให้เท่ากันกับที่คุณพูดถึงในคำถาม


1
เรียกได้ว่าเป็นต้นฉบับของassertThat()Hamcrest ดังนั้น JUnit ก็สามารถทำงานร่วมกับห้องสมุดยืนยันของบุคคลที่สามได้
Franklin Yu

ฉันเพิ่งทดสอบคำตอบนี้มันไม่ถูกต้องและนำไปสู่ข้อผิดพลาดในการรวบรวมหลายครั้ง: การเริ่มต้นที่ไม่ถูกต้องในการแสดงออก, การเริ่มต้นที่ผิดประเภท, ';' คาดว่า ... กล่าวอีกนัยหนึ่งพารามิเตอร์ตัวที่สองของคุณสำหรับ assert นั่นคือ matcher นั่นไม่สามารถเป็น "instanceof (BaseClass.class)"! ในความเป็นจริงคุณไม่ได้พิมพ์อย่างถูกต้องไวยากรณ์ที่คุณใช้นั้นแตกต่างกันเล็กน้อย - "InstanceOf (" - เป็นการเรียกใช้ฟังก์ชั่น! ไม่มีฟังก์ชั่นดังกล่าวจริง ๆ แล้ว ... มันผ่านการทดสอบจากทุกคนแล้ว? พิมพ์โดยไม่มีการทดสอบใด ๆ
Carmageddon

@Cagageddon ฉันให้คำตอบสองข้อข้อหนึ่งสำหรับ Hamcrest และอีกข้อหนึ่งสำหรับ AssertJ คุณกำลังพูดเรื่องอะไร
Franklin Yu

@Carmageddon ฉันสงสัยว่าคุณกำลังพูดถึงตัวอย่าง Hamcrest และคุณพลาดพิมพ์instanceOfเป็นinstanceof(ใจกรณี) instanceOfเป็นฟังก์ชั่นในขณะที่instanceofอยู่ในคำหลัก Java
Franklin Yu

แน่นอนฉันพูดถึง Hamcrest แล้วและฉันลองทั้งคำหลักและฟังก์ชั่นหลังจากที่ฉันสังเกตเห็นว่าคุณเขียนมันได้อย่างไร - ไม่มีฟังก์ชั่นดังกล่าว ...
Carmageddon

3

โซลูชันสำหรับ JUnit 5 สำหรับ Kotlin!

ตัวอย่างสำหรับ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))
    }

}

ตัวอย่างสำหรับ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
ขอบคุณสำหรับโซลูชัน assertJ ที่หรูหรามาก
Aleks Nine
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.