JavaHamcrest
JavaHamcrest copied to clipboard
equalTo() does not match correctly with a Long and a IsEqual Matcher for API responses
Hello,
We're using your wonderful library to assert on API responses, using RestAssured and Hamcrest.
We are doing the following:
Long expectedId = 1111L
response.then().body("id", equalTo(expectedId))
We are seeing this in the assertion failure message:
Expected: <123456L>
Actual: 123456
It looks like the String "<123456L>" is coming from the toString() on IsEqual.
Regards, Warren
I'm confused. What is the actual value passed to the matcher? Is it a long, or a Long, or a String?
A Long
Is there any way we can see the actual code which can be executed and checked. You may provide a basic feature with test case which is failing.
I checked with the Long values and the library works, there may be issue with the RestAssured library instead.
I'm confused again. Which code do you want to see? As to your original problem, if the actual value is a Long<12345> then that's what the expected value should be, rather than 12345L, as they're actually different types--although Java provides support for implicit conversion.
@sf105 I was asking for "test code" to the original poster so I can reproduce the issue. When I tried to have a Long variable and assert it with equalTo it worked for me, hence asked this question.
@tusharjoshi Understood. Thanks
@tusharjoshi All we are doing is triggering a response from an API which has a field called id, represented in Java by a Long. It doesn't seem possible to use the equalTo matcher as hopefully depicted in the initial post.
Please let me know if this remains unclear
@wjtlopez from your description and code snippet the issue does not seem to be with the hamcrest matcher but with the API you are using. Is there any way you can provide a working code snippet which I can run and check the error. A sample project on github may be using the about mention API only. If we can reproduce the issue then working on the fix if any becomes easier.
I know exactly what @wjtlopez means. I just had the exactly same problem. The JSON syntax does not differ long from integers, for the JSON syntax both int and long are just an integer number. So take in consideration the following JSON:
{ "id": 12 }
And the bellow assertion:
Long longValue = getLongValue();
response.then().body("id", is(longValue));
A library deserializing the above JSON will create an Integer object to hold the value. But in the JSON bellow the library will create a Long object to hold the value. So sometimes the above test will pass, but sometimes it will not, depending on wheter the value on the id property fits into an int or not.
{ "id": 1125899906842624 }
So the problem is that to check if two values are equal the JavaHamcrest is using the equals method, and the equals method will return false when comparing a Long with and Integer and vice versa.
I suggest the creation of a new matcher that only checks if two objects have any of the types: long, int, char, short, byte. And after checking the types the matcher checks if the integer values from the two objects are equal.
I found the use case for this when writing an integration test using Rest Assured. I can provide more details and code if necessary.
I recently ran into this via:
assertThat(Files.size(saveFile), is(not(0)));
The above is always true. That's because Files.size() returns a long and we get boxing for both sides, so it becomes equivalent to:
assertThat(Long.valueOf(0), is(not(Integer.valueOf(0))));
Since the types don't match, the is(not()) always evaluates to true, making the test buggy.
Using 0L in the original code fixes it, but it's a pretty bad a foot gun.
Ouch. Not sure what we can do about that. In meantime, I tend to use the JUnit assertNotEquals() for simple comparison.s