From 4c51ba002d8a99d6e27d8bb09f7fd2ad1ef74ae4 Mon Sep 17 00:00:00 2001 From: Kirill Artamonov Date: Wed, 10 Jul 2024 21:28:45 +0200 Subject: [PATCH 1/2] :memo: add tests documenting deserialiation of types --- .../com/tomtom/http/GroovyAPISpec.groovy | 50 +++++++++++++++++++ src/test/groovy/com/tomtom/http/Info.groovy | 10 ++++ 2 files changed, 60 insertions(+) create mode 100644 src/test/groovy/com/tomtom/http/Info.groovy diff --git a/src/test/groovy/com/tomtom/http/GroovyAPISpec.groovy b/src/test/groovy/com/tomtom/http/GroovyAPISpec.groovy index 5b55e4d..94fbe8c 100644 --- a/src/test/groovy/com/tomtom/http/GroovyAPISpec.groovy +++ b/src/test/groovy/com/tomtom/http/GroovyAPISpec.groovy @@ -205,6 +205,56 @@ class GroovyAPISpec extends HttpClientSpec { 'OPTIONS' | WireMock.&options | http.&options } + @Unroll + def 'parses decimals as doubles by default for #name'() { + given: + mock.givenThat(mockMethod(urlEqualTo('/info')) + .willReturn(ok('{"price": 10.00}'))) + + when: + def response = clientMethod(path: '/info', expecting: Map) + + then: + response.statusCode == OK + response.body == [price: 10.0] + response.body.price instanceof Double + + where: + name | mockMethod | clientMethod + 'GET' | WireMock.&get | http.&get + 'POST' | WireMock.&post | http.&post + 'PUT' | WireMock.&put | http.&put + 'DELETE' | WireMock.&delete | http.&delete + 'TRACE' | WireMock.&trace | http.&trace + 'PATCH' | WireMock.&patch | http.&patch + 'OPTIONS' | WireMock.&options | http.&options + } + + @Unroll + def 'parses decimals as given type for custom objects for #name'() { + given: + mock.givenThat(mockMethod(urlEqualTo('/info')) + .willReturn(ok('{"price": 10.00}'))) + + when: + def response = clientMethod(path: '/info', expecting: Info) + + then: + response.statusCode == OK + response.body == new Info(price: 10.0) + response.body.price instanceof BigDecimal + + where: + name | mockMethod | clientMethod + 'GET' | WireMock.&get | http.&get + 'POST' | WireMock.&post | http.&post + 'PUT' | WireMock.&put | http.&put + 'DELETE' | WireMock.&delete | http.&delete + 'TRACE' | WireMock.&trace | http.&trace + 'PATCH' | WireMock.&patch | http.&patch + 'OPTIONS' | WireMock.&options | http.&options + } + @Unroll def 'parses response body as generic for #name'() { given: diff --git a/src/test/groovy/com/tomtom/http/Info.groovy b/src/test/groovy/com/tomtom/http/Info.groovy new file mode 100644 index 0000000..0f58142 --- /dev/null +++ b/src/test/groovy/com/tomtom/http/Info.groovy @@ -0,0 +1,10 @@ +package com.tomtom.http + +import groovy.transform.EqualsAndHashCode +import groovy.transform.ToString + +@EqualsAndHashCode +@ToString +class Info { + BigDecimal price +} From 979d00ba7bbf013fdf309c30a00cd6992797832f Mon Sep 17 00:00:00 2001 From: Kirill Artamonov Date: Wed, 10 Jul 2024 21:39:10 +0200 Subject: [PATCH 2/2] :memo: add an extra test for custom object mapper --- .../com/tomtom/http/GroovyAPISpec.groovy | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/test/groovy/com/tomtom/http/GroovyAPISpec.groovy b/src/test/groovy/com/tomtom/http/GroovyAPISpec.groovy index 94fbe8c..b762ad5 100644 --- a/src/test/groovy/com/tomtom/http/GroovyAPISpec.groovy +++ b/src/test/groovy/com/tomtom/http/GroovyAPISpec.groovy @@ -20,6 +20,7 @@ import com.fasterxml.jackson.databind.ObjectMapper import com.github.tomakehurst.wiremock.client.WireMock import spock.lang.Unroll +import static com.fasterxml.jackson.databind.DeserializationFeature.* import static com.github.tomakehurst.wiremock.client.WireMock.* import static com.tomtom.http.response.ResponseCode.OK @@ -303,7 +304,26 @@ class GroovyAPISpec extends HttpClientSpec { 'OPTIONS' | WireMock.&options | http.&options } - def 'allows providing custom ObjectMapper and falls back to body as string for #name'() { + def 'allows providing custom ObjectMapper'() { + given: + def mapper = new ObjectMapper() + .enable(USE_BIG_DECIMAL_FOR_FLOATS) + def http = new HttpClient(mapper: mapper, baseUrl: "http://localhost:${mock.port()}") + mock.givenThat(get(urlEqualTo('/info')) + .willReturn(ok('{"price": 1.65}'))) + + when: + def response = http.get(path: '/info', expecting: Map) + + then: + with(response) { + statusCode == OK + body == [price: 1.65] + body.price instanceof BigDecimal + } + } + + def 'falls back to body as string for #name'() { given: def mapper = new ObjectMapper() def http = new HttpClient(mapper: mapper, baseUrl: "http://localhost:${mock.port()}")