ChatGPT解决这个技术问题 Extra ChatGPT

断言对象是特定类型

在 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 的子类的一个实例,后者不接受。
@ammoQ 很好。我没有想到子类。感谢您的澄清
正如 maba 指出的那样,考虑使用 Hamcrest。这不仅仅是为了让您有更好的工作测试。与标准 assertTrue 相比,Hamcrest 还提供了更好的故障记录。 assertTrue 只会说 expected true got false,Hamcrest 会说 expected instanced of XYZ, got instance of ABC

m
maba

您可以使用 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));
    }
}

这是正在使用的 Matcher 的链接:hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/…
仅供参考,MatcherAssert.assertThat 比 Assert.assertThat 表现更好(在出现错误的情况下提供更好的日志记录)。我建议改用它。 hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/…
这是一个微不足道的断言,如果在示例中不是真的,那将是一个编译错误!通常,您希望使用 instanceof 沿着类层次结构:BaseClass subClass = new SubClass(); assertThat(subClass, isA(SubClass.class));,但它不会编译,因为 SubClass 不是 ? super BaseClass
@TWiStErRob 我不明白你在这里想说什么......尝试将 instanceOf(BaseClass.class) 更改为 instanceOf(String.class) ,你会看到它编译得很好,但是会抛出一个 AssertionError 。
@maba,出于某种原因,他在谈论 isA ,它捕获了类,它接受 Class<T> 而不是 Class<?> (这就是 instanceOf 所做的)。由于它捕获了类,因此使用与实例不兼容的类执行 isA 将是编译时错误。 github.com/hamcrest/JavaHamcrest/issues/39
C
Carmageddon

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

assertTrue(objectUnderTest instanceof TargetObject);


如果 objectUnderTest 是 TargetObject 的子类,这仍然会导致 true 对吗?而且我认为您想测试实际类型。
我觉得这不是正确的答案。最初的问题是要求专门检查对象的确切类型的东西。该解决方案并非如此(如上面@EircG 所述),它甚至是由最初提出问题的用户提供的,因此绝对不是imo 的“正确”答案。正确答案请查看 Franklin Yu 的答案。
好吧,它有一个缺点,@EricG 提到是的,关于富兰克林的回答——我只是看了看,对我来说没有意义,所以我只是在我的项目中使用 Junit5 进行了测试——这是错误的! instanceof 没有这样的语法,也没有名为 InstanceOf 的方法!他完全错了。我仍然坚持我的答案,而且事实证明,这对至少 30 名赞成它的人有帮助! (我假设你投了反对票)。
@kekko12 我的回答也没有检查确切的类型;它接受类似于此答案的子类。我已经更新了我的答案来解决这个问题;抱歉,我没有注意到这部分有问题。我认为大多数断言库中不包含精确相等,因为它不经常使用。
@Carmageddon 如果您使用 hamcrest 断言导入,来自 Franlin Yu 的答案确实可以正常工作:``` import static org.hamcrest.CoreMatchers.instanceOf; ``` ss 根据他的代码示例。我承认虽然我忽略了富兰克林的答案,事实上,这两个答案在功能上是等效的,所以我想这最终只是一个偏好问题。
F
Franklin Yu

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 也可以与第三方断言库一起使用。
我刚刚测试了这个答案,它不正确并导致多个编译错误:表达式的非法开始,类型的非法开始,';'预期......换句话说,你的assertThat匹配器的第二个参数不能是“instanceof(BaseClass.class)”!实际上,您甚至没有正确输入,您使用的语法略有不同 - “InstanceOf(” - 作为函数调用!实际上没有这样的函数......它甚至被任何人测试过吗?它似乎是手动的没有任何测试就输入了
@Carmageddon 我提供了两个答案,一个给 Hamcrest,另一个给 AssertJ。你说的是哪一个?
@Carmageddon 我怀疑您在谈论 Hamcrest 示例,并且您将 instanceOf 输入为 instanceof (请注意)。 instanceOfa function,而 instanceofa Java keyword
我当然提到了Hamcrest,并且在我注意到你是这样写之后我尝试了关键字AND作为一个函数 - 没有这样的函数......
N
Naruto Sempai

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

}

使用`assertThat(actualException, not(instanceOf(BaseClass.class))); ` 用于阴性测试。
M
Mahmoud Mabrok

Kotlin 的 JUnit 解决方案

什么对我有用:

assert(obj is ClassName)

例如

assert(obj is User)

注意:断言来自 AssertionsJVM.kt 文件


g
gla3dr

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