jparams / to-string-verifier

To String Verifier provides an easy and convenient way to test the toString method on your class.
MIT License
32 stars 6 forks source link

Apache related presets with hashCode included uses hash comparison logic different from the one of Apache #18

Closed kulinskyvs closed 5 years ago

kulinskyvs commented 5 years ago

With latest version of ToStringVerifier (1.4.4) the verifications with Apache presets with switched "hashcode" (com.jparams.verifier.tostring.preset.Presets#APACHE_TO_STRING_BUILDER_NO_CLASS_NAME_STYLE and com.jparams.verifier.tostring.preset.Presets#APACHE_TO_STRING_BUILDER_DEFAULT_STYLE) are failing.

The code:

public String toString()
  {
    return new ToStringBuilder(this, MULTI_LINE_STYLE)
        .append("id", id)
        .append("title", title)
        .append("plannedDate", plannedDate)
        .toString();
  }

The test:

ToStringVerifier
        .forClass(Demo.class)
        .withPreset(Presets.APACHE_TO_STRING_BUILDER_MULTI_LINE_STYLE)
        .withOnlyTheseFields("id", "title", "plannedDate")
        .verify();

The result:

java.lang.AssertionError: 

Failed verification:
org.vkulinski.demolot.domain.Demo

Expected auto generated toString:
org.vkulinski.demolot.domain.Demo@5dd91bca[
  id=-4025896784895923501
  title=981da480-a039-4248-b8f3-6b4e469fbb65
  plannedDate=2018-12-14
]

To contain hash code: 41bf187d

    at com.jparams.verifier.tostring.ToStringVerifier.verify(ToStringVerifier.java:348)
    at org.vkulinski.demolot.domain.DemoTest.testToString(DemoTest.java:97)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:239)
    at org.junit.rules.RunRules.evaluate(RunRules.java:20)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.mockito.internal.runners.DefaultInternalRunner$1.run(DefaultInternalRunner.java:79)
    at org.mockito.internal.runners.DefaultInternalRunner.run(DefaultInternalRunner.java:85)
    at org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:39)
    at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.java:163)
    at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:53)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

The reason - System.identityHashCode is used to transform the hash code into string on Apache side (see org.apache.commons.lang3.builder.ToStringStyle#appendIdentityHashCode), while Integer.toHexString is used for hash code verification on the library side (see com.jparams.verifier.tostring.ToStringVerifier#verifyHashCode).

A remark: I'm using apache commons version 3.7 (it can be a recent change in this version).

jparams commented 5 years ago

Thank you for reporting this issue, it has been fixed in version 1.4.5. If you have any further issues, please let me know.

1.4.5 should sync to maven central in a few hours, so it will be available soon.

kulinskyvs commented 5 years ago

Thank you for your really very fast reaction!