在 JUnit 中是否可以断言一个对象是一个类的实例?由于各种原因,我在测试中有一个要检查其类型的对象。它是 Object1 的类型还是 Object2 的类型?
目前我有:
assertTrue(myObject instanceof Object1);
assertTrue(myObject instanceof Object2);
这行得通,但我想知道是否有一种更具表现力的方式来做到这一点。
例如:
assertObjectIsClass(myObject, Object1);
我可以这样做:
assertEquals(myObject.class, Object1.getClass());
是否有特定的断言方法可以让我以更优雅、更流畅的方式测试对象的类型?
assertTrue(myObject instanceof Object1);
和 assertEquals(myObject.class, Object1.getClass());
实际上是不同的测试吗?第一个接受 myObject 作为 Object1
的子类的一个实例,后者不接受。
assertTrue
相比,Hamcrest 还提供了更好的故障记录。 assertTrue
只会说 expected true got false
,Hamcrest 会说 expected instanced of XYZ, got instance of ABC
您可以使用 assertThat
方法和 JUnit 附带的 Matchers。
看看 this link,它稍微介绍了 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));
}
}
由于旧答案 assertThat
现在已弃用,因此我发布了正确的解决方案:
assertTrue(objectUnderTest instanceof TargetObject);
true
对吗?而且我认为您想测试实际类型。
JUnit 5 的解决方案
文档说:
但是,JUnit Jupiter 的 org.junit.jupiter.Assertions 类没有提供类似于 JUnit 4 的 org.junit.Assert 类中的 assertThat() 方法,该类接受 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
(接受子类)的行为。如果您想要完全相等的类型,我认为没有比像您在问题中提到的那样断言两个类相等更好的方法了。
assertThat()
被推迟到 Hamcrest,因此 JUnit 也可以与第三方断言库一起使用。
instanceOf
输入为 instanceof
(请注意)。 instanceOf
是 a function,而 instanceof
是 a Java keyword。
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)
}
}
Kotlin 的 JUnit 解决方案
什么对我有用:
assert(obj is ClassName)
例如
assert(obj is User)
注意:断言来自 AssertionsJVM.kt
文件
JUnit 5.8 的实验解决方案
在 Junit 5.8 中,添加了 experimental assertInstanceOf()
方法,因此您不再需要 Hamcrest 或 AssertJ。解决方案现在很简单:
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import org.junit.Test;
public class InstanceOfTest {
@Test
public void testInstanceOf() {
SubClass subClass = new SubClass();
assertInstanceOf(BaseClass.class, subClass);
}
}
instanceof
沿着类层次结构:BaseClass subClass = new SubClass(); assertThat(subClass, isA(SubClass.class));
,但它不会编译,因为SubClass
不是? super BaseClass
。instanceOf(BaseClass.class)
更改为instanceOf(String.class)
,你会看到它编译得很好,但是会抛出一个 AssertionError 。Class<T>
而不是Class<?>
(这就是 instanceOf 所做的)。由于它捕获了类,因此使用与实例不兼容的类执行 isA 将是编译时错误。 github.com/hamcrest/JavaHamcrest/issues/39