Затвердити об'єкт - це конкретний тип


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, пізніше - ні.
Еріх Кітцмюллер

@ammoQ Дуже добре. Я не думав про підкласи. Дякую за уточнення
RNJ

1
як вказує Маба, подумайте про використання Hamcrest. Це більше, ніж просто для того, щоб мати кращий робочий тест. Hamcrest також забезпечує набагато кращу реєстрацію несправності, ніж стандарт assertTrue. assertTrueпросто сказав би expected true got false, Хамкрест сказавexpected instanced of XYZ, got instance of ABC
Джон Б

Відповіді:


253

Ви можете використовувати assertThat метод та Matchers, які постачаються з JUnit.

Подивіться за цим посиланням , в якому трохи описано відповідники JUnit.

Приклад:

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
Ось посилання на Матчер,
Джон Б

3
FYI, MatcherAssert.assert, що поводиться краще (забезпечує кращий журнал у випадку помилок), ніж Assert.assertThat. Я рекомендую використовувати його замість цього. hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/…
Джон Б

13
Це тривіальне твердження і було б помилкою компіляції, якщо не вірно в прикладі! Зазвичай ви хочете знизити ієрархію класів за допомогою instanceof:, BaseClass subClass = new SubClass(); assertThat(subClass, isA(SubClass.class));але вона не компілюється, оскільки SubClassні ? super BaseClass.
TWiStErRob

3
@TWiStErRob Я не розумію, що ви тут намагаєтеся сказати ... Спробуйте змінити instanceOf(BaseClass.class)на, instanceOf(String.class)і ви побачите, що він компілюється добре, але буде викинуто AssertionError.
маба

1
@maba, він говорить про isA з якоїсь причини, яка захоплює клас, він приймає Class<T>замість Class<?>(що це робить instanceOf). Оскільки він захоплює клас, було б помилка часу компіляції зробити isA з класом, несумісним із екземпляром. github.com/hamcrest/JavaHamcrest/issues/39
Всеволод Голованов

46

Оскільки assertThatдавня відповідь тепер застаріла, я публікую правильне рішення:

assertTrue(objectUnderTest instanceof TargetObject);


2
якщо objectUnderTest є підкласом TargetObject, це все одно призведе до trueправа? І я думаю, ви хочете перевірити фактичний тип.
EricG

Я вважаю, що це НЕ правильна відповідь. Первісне запитання було запитувати щось, що конкретно перевіряє точний тип об’єкта. Це рішення не таке (як згадувалося в @EircG вище), і навіть було надано користувачем, який спочатку задав питання, тому, безумовно, не "правильний" відповідь imo. Для правильної відповіді, будь ласка, перевірте відповідь Франкліна Ю.
kekko12

Ну, у нього є зворотний бік, який @EricG згадав так, щодо відповіді Франкліна - я просто подивився на це, і це не мало сенсу для мене, тому я просто перевірив у своєму проекті з Junit5 - це неправильно !! немає такого синтаксису, наприкладof, ні методу під назвою InstanceOf! Він абсолютно помиляється. Я до сих пір стою на своїй відповіді, і, як свідчить, було корисно принаймні 30 людей, які висловили це проти! (Я припускаю, що ви відмовились).
Кармагедон

@ kekko12 Моя відповідь не перевіряє точного типу; він приймає підклас, подібний до цієї відповіді. Я оновив свою відповідь, щоб вирішити її; вибачте, що я не помітив цю частину, про яку йдеться. Я думаю, що точна рівність не включена в більшість бібліотек тверджень, оскільки вона часто не використовується.
Франклін Ю

@Carmageddon Відповідь Франліна Ю. працює добре, якщо ви використовуєте імпорт твердження hamcrest: `` `import static org.hamcrest.CoreMatchers.instanceOf; `` `ss на його зразки коду. Я визнаю, хоча я не помітив відповіді Франкліна, і насправді ці 2 відповіді є функціонально еквівалентними, тому я думаю, що це врешті-решт питання переваги.
kekko12

23

Рішення для JUnit 5

Документація говорить:

Однак org.junit.jupiter.Assertionsклас JUnit Jupiter не пропонує такого assertThat()методу, як у org.junit.Assertкласу JUnit 4, який приймає Hamcrest Matcher. Натомість розробникам рекомендується використовувати вбудовану підтримку для відповідників, що надається сторонніми бібліотеками тверджень.

Приклад для 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 також працює з сторонніми бібліотеками тверджень.
Франклін Ю

Я щойно перевірив цю відповідь, вона НЕ коректна і призводить до декількох помилок компіляції: Незаконне початок вираження, незаконне початок типу ';' очікується ... Іншими словами, другий ваш параметр assortThat matcher, НЕ МОЖЕ бути "instanceof (BaseClass.class)"! Насправді ви навіть не ввели це правильно, синтаксис, який ви використовували, дещо інший - "InstanceOf (" - як виклик функції! Насправді такої функції немає ... чи її навіть хтось перевіряв? Здається, це було вручну) набрано без жодних тестів
Carmageddon

@Carmageddon Я дав дві відповіді, одну для Hamcrest, а другу для AssertJ. Про кого ви говорите?
Франклін Ю

@Carmageddon Я підозрюю, що ви говорите про приклад Hamcrest і ви помиляєтеся набравши instanceOfяк instanceof(пам’ятайте про випадок). instanceOfє функцією , а instanceofце ключове слово Java .
Франклін Ю

Я, звичайно, посилався на 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
Дякуємо за це дуже елегантне рішення про присвоєння рішення
Aleks Nine,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.