【问题标题】:Assert an object is a specific type断言对象是特定类型
【发布时间】:2012-09-06 10:42:03
【问题描述】:

在 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。这不仅仅是为了让您有更好的工作测试。 Hamcrest 还提供比标准assertTrue 更好的故障记录。 assertTrue 只会说 expected true got false,Hamcrest 会说 expected instanced of XYZ, got instance of ABC

标签: java unit-testing junit


【解决方案1】:

你可以使用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
【解决方案2】:

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

assertTrue(objectUnderTest instanceof TargetObject);

【讨论】:

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

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(接受子类)的行为。如果您想要完全相等的类型,我认为没有比像您在问题中提到的那样断言两个类相等更好的方法了。

【讨论】:

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

JUnit 5 for 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)
    }

}

【讨论】:

  • 使用`assertThat(actualException, not(instanceOf(BaseClass.class))); ` 用于否定测试。
【解决方案5】:

JUnit for Kotlin 解决方案

什么对我有用:

assert(obj is ClassName)

例如

assert(obj is User)

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

【讨论】:

    【解决方案6】:

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

    【讨论】:

      猜你喜欢
      • 2014-11-11
      • 2016-10-14
      • 2020-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-01
      • 2012-01-03
      • 1970-01-01
      相关资源
      最近更新 更多