rest-assured: Cannot compare Long values within body

As already faced in https://groups.google.com/forum/#!topic/rest-assured/mf-VIHM-aJA, a body element cannot be compared to a long value.

I think the best solution could be to allow function passing (as for headers) in order to convert the value to a long. E.g:

long expected = 1L;
when().get("/test/{id}", expected).
then().body("id",Long::valueOf, Matchers.is(expected));

At the moment I have to compare the id value with an integer version of expected that is definitely unsafe…

About this issue

  • Original URL
  • State: open
  • Created 8 years ago
  • Reactions: 8
  • Comments: 32

Most upvoted comments

This is a Hamcrest matching issue and could be easily fixed using Hamcrest ComparatorMatcherBuilder.

Assuming this JSON as REST response, note the “salary” property having integer and double values:

[
  {
    "id": 1,
    "name": "Richard Miles",
    "age": 30,
    "salary": 1234.56
  },
  {
    "id": 2,
    "name": "Mary Stiles",
    "age": 25,
    "salary": 2500
  },
  {
    "id": 3,
    "name": "John Noakes",
    "age": 20
  }
]

To safely compare them, try to create a custom matcher that parses the values BEFORE comparing:

import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.anyOf;
import static org.hamcrest.Matchers.everyItem;
import static org.hamcrest.Matchers.nullValue;

import org.hamcrest.Matcher;
import org.hamcrest.comparator.ComparatorMatcherBuilder;

// ComparatorMatcherBuilder is a special Hamcrest class that builds custom comparing Matchers
final Matcher<Number> greaterThanOrEqualToZeroDouble = ComparatorMatcherBuilder
		// Custom comparing rule: parse the values to java.lang.Double using Number::doubleValue before comparing
		.comparedBy(Comparator.comparingDouble(Number::doubleValue))
		// Business rule (customizable): validate if matching values are greater than or equal to ZERO
		.greaterThanOrEqualTo(0D);

/*
 * Available matching builder methods:
 * ComparatorMatcherBuilder#lessThanOrEqualTo
 * ComparatorMatcherBuilder#lessThan
 * ComparatorMatcherBuilder#comparesEqualTo
 * ComparatorMatcherBuilder#greaterThan
 * ComparatorMatcherBuilder#greaterThanOrEqualTo
 */

given("https://base.url.to")
		.get("/people")
		.then()
		// Check if every item in array is greaterThanOrEqualToZeroDouble OR null
		.body("salary", everyItem(anyOf(greaterThanOrEqualToZeroDouble, nullValue())));

As it is not a RestAssured issue, I think you could close it.

Yes I mean exactly that. At the moment I solved the problem transforming the entire body to the response class and checking with assertions the object state. E.g.:

MyClass c = .... 
        then().
           extract().response().as(MyClass.class);
Assert.equals(c.getId(), expected)

Yes I’ve been thinking about function passing as well. The problem is that the api already supports the use of path arguments which will make the API twice as big if adding functions as well. I have been thinking about making “arguments” more general so that it would be possible to supply a “mapper function argument”. Maybe like this:

then().body("id", map(Long::valueOf), Matchers.is(expected));

Where map returns another implementation of the Argument class (probably Argument would implement another interface that can be common for all types (map, withArgs etc)).