简体   繁体   English

我应该单元测试hashCode / equals / toString吗?

[英]Should I unit test hashCode/equals/toString?

When writing Java classes, it's not uncommon to generate methods using your IDE such as 编写Java类时,使用IDE生成方法并不罕见

  • toString()
  • equals()
  • hashCode()

But once you've generated them using the IDE, they become part of your codebase (in SCM) and therefore all quality measuring means apply. 但是一旦使用IDE生成它们,它们就会成为代码库的一部分(在SCM中),因此所有质量测量方法都适用。

Especially the equals and hashcode methods contain lots of conditions. 特别是equals和hashcode方法包含许多条件。 If I don't write unit tests, the score on code coverage (line-, condition-, mutation-) is pretty low, especially if the class under test is not that large. 如果我不编写单元测试,代码覆盖率(line-,condition-,mutation-)的得分相当低,特别是如果被测试的类不那么大。

Some coverage tools support filtering (ie cobertura), others (ie jacoco) don't. 一些覆盖工具支持过滤(即cobertura),其他(即jacoco)则不支持。 But the coverage tools reveal just a symptom - untested code - and therefore I'm not asking, whether to suppress/ignore the symptom, but how to deal with the root cause. 但覆盖工具只露出一个症状 - 未经测试的代码 - 因此我不是在问,是否要抑制/忽略症状,而是如何处理根本原因。

Question is: should I write unit tests for these methods? 问题是:我应该为这些方法编写单元测试吗?

  • If yes, what are good reasons to do so? 如果是的话,有什么理由这样做? And what is a sensible approach? 什么是明智的做法?
  • If no, why not? 如果不是,为什么不呢?

I'm not asking for generated classes in general, like JAXB pojos, WS-Clients etc, which can be easily generated automatically and excluded from coverage analysis. 我不是要求一般生成的类,比如JAXB pojos,WS-Clients等,它们可以很容易地自动生成并从覆盖率分析中排除。

If you generate those methods, you should probably also generate the tests for it ;-) 如果你生成这些方法,你可能也应该为它生成测试;-)

It may be cumbersome to test those methods by hand but depending on what you want to ensure with your tests, it might be worth to test those methods as well. 手动测试这些方法可能很麻烦,但根据您希望通过测试确保的方法,测试这些方法也许值得。 Counter-question: would you test log-statements? 反问题:你会测试日志声明吗?

It really depends on what you are trying to accomplish. 这实际上取决于你想要完成的事情。 Some will say: don't, others may say: do. 有些人会说:不要,别人可能会说:做。

Thinking about some reasons to not test such methods: 考虑不测试此类方法的一些原因:

  • code is generated and may contain lots of fields. 代码生成并可能包含许多字段。 testing it may lead to lots of various combinations which would just be cumbersome to write/maintain and maybe the generator was already tested good enough? 测试它可能导致许多各种组合,这些组合只是编写/维护很麻烦,也许发电机已经测试好了吗? ;-) ;-)
  • you do not gain any value by implementing tests for it. 你没有通过实施测试获得任何价值。 Your toString() will only be used by logs or by the debugger, so you don't even care. 你的toString()只会被日志或调试器使用,所以你甚至不关心。
  • you trust that the generated code is safe enough for hashcode and equals 您相信生成的代码对于hashcodeequals足够安全

Reasons to test such methods: 测试此类方法的原因:

  • to ensure that the outcome is as expected 确保结果符合预期
  • you want to ensure that if you regenerate those methods, it doesn't break previous method implementation usages 您希望确保如果重新生成这些方法,它不会破坏以前的方法实现用法
  • you use your toString() -method besides logging and don't want certain things to show up there. 除了记录之外你还使用toString()方法,并且不希望某些东西显示在那里。 As Hulk stated, you may also want to ensure that certain things don't even show up in logs. 正如Hulk所说,你可能还想确保某些东西甚至不会出现在日志中。

But these were rather made up. 但这些都是相当弥补的。 In the last projects I did not test toString() and equals or hashCode only seldomly as it wasn't considered necessary and everyone agreed. 在最后的项目中,我没有测试toString()equalshashCode很少,因为它不被认为是必要的,每个人都同意。

It may all come down to: how safe you want your code to be and how much worth is it to you (or your business or your customer ;-)) 这可能归结为:您希望代码的安全性如何以及对您(或您的企业或客户;-)的价值有多大)

The problem with IDE generated hashCode/equals is that it can get out of sync with the object itself (for example when you add new fields). IDE生成的hashCode / equals的问题是它可能与对象本身不同步(例如,当您添加新字段时)。 I would therefore advise to create tests for hashCode and equals. 因此,我建议为hashCode和equals创建测试。

It would be of course sub-optimal to write these by hand. 手动编写这些当然是次优的。 You can use automated tools such as the EqualsVerifier project to make these a one-liner. 您可以使用EqualsVerifier项目等自动化工具将这些工具作为单行程序。

toString is a different beast as it doesn't have any contract defined. toString是一个不同的野兽,因为它没有定义任何合同。 If you use toString just to get a nicer debugging experience, I wouldn't test it and would just remove it from coverage calculations. 如果你只是为了获得更好的调试体验而使用toString,我就不会测试它,只是将其从覆盖率计算中删除。

Yes, I would test all of these. 是的,我会测试所有这些。 Its not good enough to say, no tests needs as they are auto generated. 它不够好,没有测试需要,因为它们是自动生成的。 Some one can easily add a new field and forget to regenerate the equals/ hash code and to string. 有些人可以轻松添加新字段,忘记重新生成equals / hash代码和字符串。

Testing to string is perhaps the most controversial of the lot, but I think its needed especially if you are logging in your application. 对字符串进行测试可能是该批次中最具争议性的,但我认为特别是在您登录应用程序时需要它。

As already suggested by other, EqualsVerifier is probably the best approach for testing equals and hash code. 正如其他人已经建议的那样, EqualsVerifier可能是测试equals和hash代码的最佳方法。

As for testing the toString method, try ToStringVerifier . 至于测试toString方法,请尝试ToStringVerifier The test is as simple as: 测试很简单:

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

These methods are useless by themselves. 这些方法本身毫无用处。 If you don't use those classes in collections (like HashSet / HashMap ) or if you never check those class instances for equality - you don't need unit tests. 如果您不在集合中使用这些类(如HashSet / HashMap ),或者您从不检查这些类实例是否相等 - 则不需要单元测试。 And, in this case, i would just disable plugin that generates them, as @ByeBye proposed. 并且,在这种情况下,我将禁用生成它们的插件,如@ByeBye所提议的那样。

But, if you actually do any of that, you need unit tests. 但是,如果你真的这样做,你需要进行单元测试。 If incorrect implementation can cause your application failure or incorrect behavior - this implementation has to be covered with unit tests. 如果不正确的实现可能导致应用程序失败或行为不正确 - 此实现必须通过单元测试来涵盖。

Same for external libraries - you shouldn't tests equals and hashcode methods when you generating that. 对于外部库也是如此 - 在生成外部库时,不应该测试equalshashcode方法。 Plugin which checking coverage should have some mechanism to ignore that generated sources. 检查覆盖范围的插件应该有一些机制来忽略生成的源。

There is no good reason to test generated code, no difference if this is generated method in your class, or whole class. 没有充分的理由来测试生成的代码,如果这是您的类或整个类中生成的方法没有区别。

If you depending on external mechanism you should believe that it is created properly. 如果您依赖外部机制,您应该相信它是正确创建的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM