断言对象是特定类型


195

在JUnit中是否可以断言一个对象是一个类的实例?由于各种原因,我在测试中有一个要检查其类型的对象。它是Object1还是Object2?

目前我有:

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

这行得通,但我想知道是否有一种更具表现力的方式来做到这一点。

例如:

assertObjectIsClass(myObject, Object1);

我可以这样做:

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

有没有一种特定的assert方法,可以让我以更优雅,更流畅的方式测试对象的类型?


15
您是否知道assertTrue(myObject instanceof Object1);assertEquals(myObject.class, Object1.getClass());实际上是不同的测试?第一个接受myObject是的子类的实例Object1,第二个不接受。
Erich Kitzmueller 2012年

@ammoQ非常好。我没想到子类。感谢您的clarifaction
RNJ

1
正如maba指出的那样,请考虑使用Hamcrest。这不仅仅是为了使您有更好的工作测试。Hamcrest还提供了比标准更好的故障记录功能assertTrueassertTrue只会说expected true got false,哈姆雷斯特会说expected instanced of XYZ, got instance of ABC
约翰·B

Answers:


253

您可以使用assertThatJUnit随附的方法和Matchers。

看一下这个链接,它描述了有关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));
    }
}


3
仅供参考,MatcherAssert.assertThat比Assert.assertThat表现得更好(在出现错误的情况下提供更好的日志记录)。我建议改用它。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 2014年

3
@TWiStErRob我不明白您要在此处说的是什么...尝试将to更改instanceOf(BaseClass.class)instanceOf(String.class),您将看到它可以正常编译,但是会抛出AssertionError。
maba 2014年

1
@maba,出于某种原因,他在谈论isA,它捕获了类,而是接受Class<T>了它Class<?>(而不是instanceOf所做的)。因为它捕获了类,所以对与实例不兼容的类执行isA会导致编译时错误。github.com/hamcrest/JavaHamcrest/issues/39
Vsevolod Golovanov

46

由于assertThat旧的答案现在已被弃用,因此我发布了正确的解决方案:

assertTrue(objectUnderTest instanceof TargetObject);


2
如果objectUnderTest是TargetObject的子类,这是否仍然会true正确?而且我认为您想测试实际的类型。
EricG '18

我觉得这不是正确的答案。最初的问题是要求一些专门检查对象确切类型的东西。该解决方案不是那样的(如上面@EircG所提到的),它甚至是由最初问问题的用户提供的,因此绝对不是“正确”的答案imo。对于正确的答案,请检查Franklin Yu答案。
kekko12

好吧,它有一个缺点,@ EricG提到了富兰克林的答案-我只是看了一下,对我来说没有任何意义,所以我只是在Junit5的项目中进行了测试-这是错误的!没有instanceof这样的语法,也没有名为InstanceOf!的方法。他是完全错误的。我仍然坚持我的回答,并且事实证明,这对至少30个支持它的人很有帮助!(我假设你投票否定)。
Carmageddon

@ kekko12我的答案也没有检查确切的类型;它接受类似于此答案的子类。我已经更新了答案以解决该问题;很抱歉,我没有注意到有问题的部分。我认为大多数断言库中不包括精确相等性,因为它不经常使用。
富兰克林于

@Carmageddon 如果您使用hamcrest断言导入,来自Franlin Yu的答案确实可以很好地工作:根据他的代码示例。我确实承认,尽管我忽略了富兰克林的答案,但实际上,这两个答案在功能上是等效的,因此我想这最终只是一个偏好问题。
kekko12

21

JUnit 5的解决方案

该文档说:

但是,JUnit Jupiter的org.junit.jupiter.Assertions类没有提供assertThat()像在JUnit 4的org.junit.Assert类中找到的接受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我提供了两个答案,一个答案给Hamcrest,另一个答案给AssertJ。你在说哪一个?
富兰克林于

@Carmageddon我怀疑你是在谈论Hamcrest例子,你错过类型的instanceOf作为instanceof(介意的情况下)。instanceOf一个函数,同时instanceofJava关键字
富兰克林于

我当然提到了Hamcrest,在我注意到那是你写的方式之后,我尝试了两个关键字AND作为一个函数-没有这样的函数...
Carmageddon

3

Kotlin的JUnit 5解决方案!

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.