【问题标题】:Generate unit tests for hashcode,equals and toString methods为 hashcode、equals 和 toString 方法生成单元测试
【发布时间】:2012-05-17 09:28:21
【问题描述】:

是否有任何工具/库可以自动为我的哈希码生成测试并查看这些方法中涉及的实例变量的 equals 方法?

【问题讨论】:

  • 这样的测试没有实质意义,但主要是介绍维护。
  • @MPlatvoet 我不太同意你的观点,测试equals() 和hashcode() 可能很重要,特别是如果你的某些代码严重依赖它(HashMap,涉及继承的相等测试)
  • @Colin Hebert 那么你会预先编写一个测试,它规定了一些要求。生成测试只会确认您在编写实现时引入的相同可能错误。因此,现在它仅在您需要更改实现时才成为维护添加。
  • @buymypies 我正在使用 eclipse
  • @MPlatvoet 我同意您的想法,即这些测试将复制源代码中的错误。但是使用这种方式,我们可以确保没有人意外地从这些方法中删除变量。

标签: java


【解决方案1】:

Guava 使用this 测试生成器来测试equals 和hashCode。

【讨论】:

    【解决方案2】:

    toString() 不应该有任何要尊重的“合同”,所以单元测试会很奇怪而且没有用处。

    关于equals(),你可以看看这个project。

    还有一个 JUnit 插件EqualsHashCodeTestCase


    关于同一主题:

    【讨论】:

    • 我不明白为什么 toString 没有规范,尽管我自己从未对它进行过单元测试。
    • 好吧,我不是说它不能,但它不应该。 toString() 是对象的字符串表示,因此它可以被人读取(参见 javadoc for Object),所以这表示它基本上不应该做任何“极端”的事情(它是对象的表示,而不是业务方法) 并且它返回一个可供人类阅读而不是解析的字符串。从那里很容易说 toString 不应该进行单元测试(不是“不能”或“不能”)。
    • 是的,如果您对所有类进行全面测试,那么它没有任何意义。请注意,对于特定类别仍然是合法的,请对toString 提出更严格的要求。 JSE 本身就有很多例子(StringWriter,StringBuilder,URL,...)。
    • 我倾向于同意(并且在其他 SO 帖子中也有同样的争论),但它经常在 Web 开发中用作在网页上显示信息的快捷方式,例如。对于简单的 DTO,我猜我对这种滥用并不那么坚决……但最终,在相关应用程序的上下文中强制执行“人类可读”意味着什么,我没有问题。这是一个相对较小的问题;我只是觉得想想很有趣,因为我从来没有:)
    • @MarkoTopolnik 我同意你的观点,有时toString() 需要有一定的意义,但即使在这些情况下,我也不确定单元测试是否相关。这与测试 getter/setter 不同,但它有点接近。测试本身几乎没有任何意义(如果连接在 java 中有效,你最终会检查更多而不是测试实际方法)。
    【解决方案3】:

    EqualsVerifier 是一个很棒的库。我经常将它与Reflections 库结合使用,以自动扫描某些类并一次性测试所有类的契约:

     @Test
      public void validateEqualsHashCodeToString() {
        final Reflections dtoClassesReflections = new Reflections(new ConfigurationBuilder()
          .setUrls(ClasspathHelper.forPackage("my.base.package"))
          .filterInputsBy(new FilterBuilder()
            .include(".*Dto.*") // include all Dto classes
            .exclude(".*Test.*")) // exclude classes from tests which will be scanned as well
          .setScanners(new SubTypesScanner(false)));
    
        final Set<Class<?>> allDtoClasses = dtoClassesReflections.getSubTypesOf(Object.class);
    
        allDtoClasses.forEach(dtoClass -> {
          logger.info("equals/hashCode tester testing: " + dtoClass);
          EqualsVerifier.forClass(dtoClass).verify();
    
          try {
            dtoClass.getDeclaredMethod("toString");
          } catch (NoSuchMethodException e) {
            fail(dtoClass + " does not override toString() method");
          }
        });
      }
    

    【讨论】:

      【解决方案4】:

      我会推荐EqualsVerifier 来测试哈希码和equals方法。

      我会推荐 ToStringVerifier 来测试 toString 方法

      这是一个例子:

      @Test
      public void testToString()
      {
          ToStringVerifier.forClass(User.class).verify();
      }
      

      【讨论】:

        【解决方案5】:

        您可以使用 Apache EqualsBuilder 和 HashCodeBuilder 来实现 equals 和 hashCode,从而将不正确执行的风险降至最低。

        测试equals很简单,创建两个实例值相同的实例(您会期望它们相等)并在一个实例上调用equals并将另一个作为参数传递,您应该期望它返回true:D

        【讨论】:

        • 问题是,如何测试 hashCode 合约没有被破坏。应该如何实现测试,检查以下两件事: 1. 如果 equals 返回 true,则 hashCode 必须返回相同的值。 2.如果hashCode返回不同​​的值,那么equals一定返回false。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-25
        • 2012-02-17
        • 2013-07-28
        • 2021-10-29
        • 1970-01-01
        相关资源
        最近更新 更多