Утвердить объект определенного типа


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 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/…
Джон B

3
К вашему сведению, MatcherAssert.assertThat ведет себя лучше (обеспечивает лучшую регистрацию в случае ошибок), чем 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
Всеволод Голованов

47

Поскольку assertThatпрежний ответ устарел, я выкладываю правильное решение:

assertTrue(objectUnderTest instanceof TargetObject);


2
если objectUnderTest является подклассом TargetObject, это все равно приведет к trueправильному? И я думаю, что вы хотите проверить фактический тип.
EricG

Я чувствую, что это не правильный ответ. Первоначальный вопрос спрашивал о чем-то, что конкретно проверяет точный тип объекта. Это решение не так (как упомянуто выше @EircG), и оно даже было предоставлено пользователем, первоначально задававшим вопрос, поэтому определенно не «правильный» ответ imo. Для правильного ответа, пожалуйста, проверьте ответ Франклин Ю.
kekko12

Ну, у него есть и обратная сторона, о которой @EricG упомянул да, об ответе Франклина - я только посмотрел на него, и это не имело смысла для меня, поэтому я только что проверил в своем проекте с Junit5 - это неправильно !! для instanceof нет ни такого синтаксиса, ни метода InstanceOf! Он совершенно не прав. Я стою на своем ответе до сих пор, и, как свидетельствует, это было полезно по крайней мере 30 человек, которые проголосовали за него! (Я полагаю, вы проголосовали)
Carmageddon

@ kekko12 Мой ответ также не проверяет точный тип; он принимает подкласс, похожий на этот ответ. Я обновил свой ответ, чтобы обратиться к нему; извините, что не заметил эту часть вопроса. Я думаю, что точное равенство не включено в большинство библиотек утверждений, потому что оно не часто используется.
Франклин Ю

@Carmageddon Ответ от Franlin Yu работает нормально, если вы используете импорт утверждений 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 также работает со сторонними библиотеками утверждений.
Франклин Ю

Я только что проверил этот ответ, он НЕ верен и приводит к множественным ошибкам компиляции: Недопустимое начало выражения, недопустимое начало типа, ';' ожидается ... Другими словами, ваш второй параметр для сопоставления assertThat НЕ МОЖЕТ быть "instanceof (BaseClass.class)"! На самом деле, вы даже не набрали это правильно, синтаксис, который вы использовали, немного отличается - «InstanceOf (») как вызов функции! На самом деле такой функции нет ... она вообще была проверена кем-то? Кажется, это было вручную набран без каких - либо испытаний
Carmageddon

@Carmageddon Я предоставил два ответа, один для Хэмкреста и другой для AssertJ. О ком ты говоришь?
Франклин Ю

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

Я, конечно, ссылался на Hamcrest one, и я попробовал оба ключевых слова AND как функцию после того, как заметил, что вы так и написали - такой функции нет ...
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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.