You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ja...@apache.org on 2022/05/23 20:18:14 UTC
[camel-quarkus] branch main updated: Use WireMock for xchange tests
This is an automated email from the ASF dual-hosted git repository.
jamesnetherton pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
The following commit(s) were added to refs/heads/main by this push:
new d465a84e9f Use WireMock for xchange tests
d465a84e9f is described below
commit d465a84e9f9faf0bd74becb74bf542906543e1b1
Author: James Netherton <ja...@gmail.com>
AuthorDate: Mon May 23 11:18:28 2022 +0100
Use WireMock for xchange tests
Fixes #3724
---
integration-tests/xchange/README.adoc | 18 ++++++++
integration-tests/xchange/pom.xml | 4 ++
.../component/xchange/it/XchangeResource.java | 49 +++++++++++++++++++---
.../xchange/it/XchangeBinanceTestResource.java | 45 ++++++++++++++++++++
.../xchange/it/XchangeKrakenTestResource.java | 45 ++++++++++++++++++++
.../quarkus/component/xchange/it/XchangeTest.java | 6 ++-
...pairs-3a81de1f-2691-412e-8896-3bac2239f07d.json | 1 +
...ssets-23a47848-dae8-4bdb-9ac7-851012c5b102.json | 1 +
...einfo-41fc7d67-259d-4bf2-944d-8a00f9c2370a.json | 1 +
...pairs-3a81de1f-2691-412e-8896-3bac2239f07d.json | 29 +++++++++++++
...ssets-23a47848-dae8-4bdb-9ac7-851012c5b102.json | 29 +++++++++++++
...icker-9b4fb7b4-081c-4965-beae-7a5d5c9869e9.json | 29 +++++++++++++
...einfo-41fc7d67-259d-4bf2-944d-8a00f9c2370a.json | 38 +++++++++++++++++
..._24hr-32b9aee3-92c1-45ac-af48-7fd4b7f67da9.json | 38 +++++++++++++++++
14 files changed, 326 insertions(+), 7 deletions(-)
diff --git a/integration-tests/xchange/README.adoc b/integration-tests/xchange/README.adoc
new file mode 100644
index 0000000000..ef18b63bcf
--- /dev/null
+++ b/integration-tests/xchange/README.adoc
@@ -0,0 +1,18 @@
+== Camel Quarkus XChange Integration Tests
+
+By default the XChange integration tests use WireMock to stub the API interactions.
+
+To run the `camel-quarkus-xchange` integration tests against the real APIs, you can set the following environment variable:
+
+[source,shell]
+----
+export CAMEL_QUARKUS_START_MOCK_BACKEND=false
+----
+
+If the WireMock stub recordings need updating, then remove the existing files from `src/test/resources/mappings` and run tests with either:
+
+System property `-Dwiremock.record=true`
+
+Or
+
+Set environment variable `WIREMOCK_RECORD=true`
diff --git a/integration-tests/xchange/pom.xml b/integration-tests/xchange/pom.xml
index 48b26000aa..52a7b64f0f 100644
--- a/integration-tests/xchange/pom.xml
+++ b/integration-tests/xchange/pom.xml
@@ -61,6 +61,10 @@
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.apache.camel.quarkus</groupId>
+ <artifactId>camel-quarkus-integration-wiremock-support</artifactId>
+ </dependency>
</dependencies>
<profiles>
diff --git a/integration-tests/xchange/src/main/java/org/apache/camel/quarkus/component/xchange/it/XchangeResource.java b/integration-tests/xchange/src/main/java/org/apache/camel/quarkus/component/xchange/it/XchangeResource.java
index e79642b6d8..4203de4185 100644
--- a/integration-tests/xchange/src/main/java/org/apache/camel/quarkus/component/xchange/it/XchangeResource.java
+++ b/integration-tests/xchange/src/main/java/org/apache/camel/quarkus/component/xchange/it/XchangeResource.java
@@ -16,7 +16,9 @@
*/
package org.apache.camel.quarkus.component.xchange.it;
+import java.net.URI;
import java.util.List;
+import java.util.Optional;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
@@ -33,17 +35,26 @@ import javax.ws.rs.core.MediaType;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.component.xchange.XChangeComponent;
+import org.apache.camel.spi.annotations.Component;
+import org.eclipse.microprofile.config.Config;
+import org.eclipse.microprofile.config.ConfigProvider;
+import org.knowm.xchange.Exchange;
+import org.knowm.xchange.ExchangeFactory;
+import org.knowm.xchange.ExchangeSpecification;
+import org.knowm.xchange.binance.BinanceExchange;
import org.knowm.xchange.currency.Currency;
import org.knowm.xchange.currency.CurrencyPair;
import org.knowm.xchange.dto.marketdata.Ticker;
import org.knowm.xchange.dto.meta.CurrencyMetaData;
import org.knowm.xchange.dto.meta.CurrencyPairMetaData;
+import org.knowm.xchange.kraken.KrakenExchange;
@Path("/xchange")
@ApplicationScoped
public class XchangeResource {
public static final String DEFAULT_CRYPTO_EXCHANGE = "binance";
+ public static final String ALTERNATIVE_CRYPTO_EXCHANGE = "kraken";
@Inject
ProducerTemplate producerTemplate;
@@ -55,10 +66,8 @@ public class XchangeResource {
@PathParam("exchange") String cryptoExchange,
@QueryParam("currencyPair") String currencyPair) {
- String component = cryptoExchange.equals(DEFAULT_CRYPTO_EXCHANGE) ? "xchange" : "xchange-" + cryptoExchange;
-
Ticker ticker = producerTemplate.requestBody(
- component + ":" + cryptoExchange + "?service=marketdata&method=ticker¤cyPair=" + currencyPair, null,
+ "xchange:" + cryptoExchange + "?service=marketdata&method=ticker¤cyPair=" + currencyPair, null,
Ticker.class);
return Json.createObjectBuilder()
.add("last", ticker.getLast().longValue())
@@ -114,10 +123,38 @@ public class XchangeResource {
return metaData.getTradingFee().toPlainString();
}
- @Named("xchange-kraken")
+ @Named("xchange")
public XChangeComponent xChangeComponent() {
- // We are forced to create a dedicated component instance to work with multiple crypto exchanges
- // https://issues.apache.org/jira/browse/CAMEL-16978
+ Config config = ConfigProvider.getConfig();
+ Optional<String> wireMockUrl = config.getOptionalValue("wiremock.url", String.class);
+ if (wireMockUrl.isPresent()) {
+ return new WireMockedXChangeComponent();
+ }
return new XChangeComponent();
}
+
+ @Component("xchange")
+ static final class WireMockedXChangeComponent extends XChangeComponent {
+ @Override
+ protected Exchange createExchange(Class<? extends Exchange> exchangeClass) {
+ String wireMockUrlProperty;
+ if (exchangeClass.equals(BinanceExchange.class)) {
+ wireMockUrlProperty = "wiremock.binance.url";
+ } else if (exchangeClass.equals(KrakenExchange.class)) {
+ wireMockUrlProperty = "wiremock.kraken.url";
+ } else {
+ throw new IllegalStateException("Unsupported WireMocked exchange " + exchangeClass.getSimpleName());
+ }
+
+ Config config = ConfigProvider.getConfig();
+ String wireMockUrl = config.getValue(wireMockUrlProperty, String.class);
+ URI uri = URI.create(wireMockUrl);
+
+ ExchangeSpecification specification = new ExchangeSpecification(exchangeClass);
+ specification.setHost("localhost");
+ specification.setPort(uri.getPort());
+ specification.setSslUri(wireMockUrl);
+ return ExchangeFactory.INSTANCE.createExchange(specification);
+ }
+ }
}
diff --git a/integration-tests/xchange/src/test/java/org/apache/camel/quarkus/component/xchange/it/XchangeBinanceTestResource.java b/integration-tests/xchange/src/test/java/org/apache/camel/quarkus/component/xchange/it/XchangeBinanceTestResource.java
new file mode 100644
index 0000000000..04ad911fac
--- /dev/null
+++ b/integration-tests/xchange/src/test/java/org/apache/camel/quarkus/component/xchange/it/XchangeBinanceTestResource.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.component.xchange.it;
+
+import java.util.Map;
+
+import org.apache.camel.quarkus.test.mock.backend.MockBackendUtils;
+import org.apache.camel.quarkus.test.wiremock.WireMockTestResourceLifecycleManager;
+
+public class XchangeBinanceTestResource extends WireMockTestResourceLifecycleManager {
+
+ @Override
+ public Map<String, String> start() {
+ Map<String, String> options = super.start();
+ String wireMockUrl = options.get("wiremock.url");
+ if (wireMockUrl != null) {
+ options.put("wiremock.binance.url", wireMockUrl);
+ }
+ return options;
+ }
+
+ @Override
+ protected String getRecordTargetBaseUrl() {
+ return "https://api.binance.com/";
+ }
+
+ @Override
+ protected boolean isMockingEnabled() {
+ return MockBackendUtils.startMockBackend(false);
+ }
+}
diff --git a/integration-tests/xchange/src/test/java/org/apache/camel/quarkus/component/xchange/it/XchangeKrakenTestResource.java b/integration-tests/xchange/src/test/java/org/apache/camel/quarkus/component/xchange/it/XchangeKrakenTestResource.java
new file mode 100644
index 0000000000..7fd83202c3
--- /dev/null
+++ b/integration-tests/xchange/src/test/java/org/apache/camel/quarkus/component/xchange/it/XchangeKrakenTestResource.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.component.xchange.it;
+
+import java.util.Map;
+
+import org.apache.camel.quarkus.test.mock.backend.MockBackendUtils;
+import org.apache.camel.quarkus.test.wiremock.WireMockTestResourceLifecycleManager;
+
+public class XchangeKrakenTestResource extends WireMockTestResourceLifecycleManager {
+
+ @Override
+ public Map<String, String> start() {
+ Map<String, String> options = super.start();
+ String wireMockUrl = options.get("wiremock.url");
+ if (wireMockUrl != null) {
+ options.put("wiremock.kraken.url", wireMockUrl);
+ }
+ return options;
+ }
+
+ @Override
+ protected String getRecordTargetBaseUrl() {
+ return "https://api.kraken.com/";
+ }
+
+ @Override
+ protected boolean isMockingEnabled() {
+ return MockBackendUtils.startMockBackend(false);
+ }
+}
diff --git a/integration-tests/xchange/src/test/java/org/apache/camel/quarkus/component/xchange/it/XchangeTest.java b/integration-tests/xchange/src/test/java/org/apache/camel/quarkus/component/xchange/it/XchangeTest.java
index cc3522daae..ba310e9d35 100644
--- a/integration-tests/xchange/src/test/java/org/apache/camel/quarkus/component/xchange/it/XchangeTest.java
+++ b/integration-tests/xchange/src/test/java/org/apache/camel/quarkus/component/xchange/it/XchangeTest.java
@@ -16,12 +16,14 @@
*/
package org.apache.camel.quarkus.component.xchange.it;
+import io.quarkus.test.common.QuarkusTestResource;
import io.quarkus.test.junit.QuarkusTest;
import io.restassured.RestAssured;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
+import static org.apache.camel.quarkus.component.xchange.it.XchangeResource.ALTERNATIVE_CRYPTO_EXCHANGE;
import static org.apache.camel.quarkus.component.xchange.it.XchangeResource.DEFAULT_CRYPTO_EXCHANGE;
import static org.hamcrest.Matchers.emptyOrNullString;
import static org.hamcrest.Matchers.greaterThan;
@@ -29,10 +31,12 @@ import static org.hamcrest.Matchers.hasItems;
import static org.hamcrest.Matchers.not;
@QuarkusTest
+@QuarkusTestResource(XchangeBinanceTestResource.class)
+@QuarkusTestResource(XchangeKrakenTestResource.class)
class XchangeTest {
@ParameterizedTest
- @ValueSource(strings = { DEFAULT_CRYPTO_EXCHANGE, "kraken" })
+ @ValueSource(strings = { DEFAULT_CRYPTO_EXCHANGE, ALTERNATIVE_CRYPTO_EXCHANGE })
public void currencyTicker(String cryptoExchange) {
RestAssured.given()
.queryParam("currencyPair", "BTC/USDT")
diff --git a/integration-tests/xchange/src/test/resources/__files/0_public_assetpairs-3a81de1f-2691-412e-8896-3bac2239f07d.json b/integration-tests/xchange/src/test/resources/__files/0_public_assetpairs-3a81de1f-2691-412e-8896-3bac2239f07d.json
new file mode 100644
index 0000000000..6c010dd818
--- /dev/null
+++ b/integration-tests/xchange/src/test/resources/__files/0_public_assetpairs-3a81de1f-2691-412e-8896-3bac2239f07d.json
@@ -0,0 +1 @@
+{"error":[],"result":{"1INCHEUR":{"altname":"1INCHEUR","wsname":"1INCH/EUR","aclass_base":"currency","base":"1INCH","aclass_quote":"currency","quote":"ZEUR","lot":"unit","pair_decimals":3,"lot_decimals":8,"lot_multiplier":1,"leverage_buy":[],"leverage_sell":[],"fees":[[0,0.26],[50000,0.24],[100000,0.22],[250000,0.2],[500000,0.18],[1000000,0.16],[2500000,0.14],[5000000,0.12],[10000000,0.1]],"fees_maker":[[0,0.16],[50000,0.14],[100000,0.12],[250000,0.1],[500000,0.08],[1000000,0.06],[250000 [...]
\ No newline at end of file
diff --git a/integration-tests/xchange/src/test/resources/__files/0_public_assets-23a47848-dae8-4bdb-9ac7-851012c5b102.json b/integration-tests/xchange/src/test/resources/__files/0_public_assets-23a47848-dae8-4bdb-9ac7-851012c5b102.json
new file mode 100644
index 0000000000..e26ee5e838
--- /dev/null
+++ b/integration-tests/xchange/src/test/resources/__files/0_public_assets-23a47848-dae8-4bdb-9ac7-851012c5b102.json
@@ -0,0 +1 @@
+{"error":[],"result":{"1INCH":{"aclass":"currency","altname":"1INCH","decimals":10,"display_decimals":5},"AAVE":{"aclass":"currency","altname":"AAVE","decimals":10,"display_decimals":5},"ACA":{"aclass":"currency","altname":"ACA","decimals":10,"display_decimals":5},"ADA":{"aclass":"currency","altname":"ADA","decimals":8,"display_decimals":6},"ADA.S":{"aclass":"currency","altname":"ADA.S","decimals":8,"display_decimals":6},"AGLD":{"aclass":"currency","altname":"AGLD","decimals":10,"display [...]
\ No newline at end of file
diff --git a/integration-tests/xchange/src/test/resources/__files/api_v3_exchangeinfo-41fc7d67-259d-4bf2-944d-8a00f9c2370a.json b/integration-tests/xchange/src/test/resources/__files/api_v3_exchangeinfo-41fc7d67-259d-4bf2-944d-8a00f9c2370a.json
new file mode 100644
index 0000000000..9d1f31dc7e
--- /dev/null
+++ b/integration-tests/xchange/src/test/resources/__files/api_v3_exchangeinfo-41fc7d67-259d-4bf2-944d-8a00f9c2370a.json
@@ -0,0 +1 @@
+{"timezone":"UTC","serverTime":1653300040347,"rateLimits":[{"rateLimitType":"REQUEST_WEIGHT","interval":"MINUTE","intervalNum":1,"limit":1200},{"rateLimitType":"ORDERS","interval":"SECOND","intervalNum":10,"limit":50},{"rateLimitType":"ORDERS","interval":"DAY","intervalNum":1,"limit":160000},{"rateLimitType":"RAW_REQUESTS","interval":"MINUTE","intervalNum":5,"limit":6100}],"exchangeFilters":[],"symbols":[{"symbol":"ETHBTC","status":"TRADING","baseAsset":"ETH","baseAssetPrecision":8,"quot [...]
\ No newline at end of file
diff --git a/integration-tests/xchange/src/test/resources/mappings/0_public_assetpairs-3a81de1f-2691-412e-8896-3bac2239f07d.json b/integration-tests/xchange/src/test/resources/mappings/0_public_assetpairs-3a81de1f-2691-412e-8896-3bac2239f07d.json
new file mode 100644
index 0000000000..efc9e74ea2
--- /dev/null
+++ b/integration-tests/xchange/src/test/resources/mappings/0_public_assetpairs-3a81de1f-2691-412e-8896-3bac2239f07d.json
@@ -0,0 +1,29 @@
+{
+ "id" : "3a81de1f-2691-412e-8896-3bac2239f07d",
+ "name" : "0_public_assetpairs",
+ "request" : {
+ "url" : "/0/public/AssetPairs",
+ "method" : "GET"
+ },
+ "response" : {
+ "status" : 200,
+ "bodyFileName" : "0_public_assetpairs-3a81de1f-2691-412e-8896-3bac2239f07d.json",
+ "headers" : {
+ "Date" : "Mon, 23 May 2022 10:00:43 GMT",
+ "Content-Type" : "application/json",
+ "strict-transport-security" : "max-age=15768000",
+ "cache-control" : "public, max-age=1, s-maxage=1",
+ "referrer-policy" : "strict-origin-when-cross-origin",
+ "Last-Modified" : "Mon, 23 May 2022 10:00:43 GMT",
+ "CF-Cache-Status" : "HIT",
+ "Age" : "0",
+ "Expect-CT" : "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"",
+ "Set-Cookie" : "__cf_bm=uVwO8iZAmsSOoFZJFL.adKZIhsgJyaeCzuDdnYLbSRA-1653300043-0-AWCUFlfFL/e3ROoR/yQ9vzEjMnQ8K07asrciF8fCNbyo50hLK9qLmkFDznBTJv44kAeyVby9C/qL2EKiih+BqQM=; path=/; expires=Mon, 23-May-22 10:30:43 GMT; domain=.kraken.com; HttpOnly; Secure; SameSite=None",
+ "Server" : "cloudflare",
+ "CF-RAY" : "70fcf237e8e274a1-LHR"
+ }
+ },
+ "uuid" : "3a81de1f-2691-412e-8896-3bac2239f07d",
+ "persistent" : true,
+ "insertionIndex" : 1
+}
\ No newline at end of file
diff --git a/integration-tests/xchange/src/test/resources/mappings/0_public_assets-23a47848-dae8-4bdb-9ac7-851012c5b102.json b/integration-tests/xchange/src/test/resources/mappings/0_public_assets-23a47848-dae8-4bdb-9ac7-851012c5b102.json
new file mode 100644
index 0000000000..e9ea23eeb9
--- /dev/null
+++ b/integration-tests/xchange/src/test/resources/mappings/0_public_assets-23a47848-dae8-4bdb-9ac7-851012c5b102.json
@@ -0,0 +1,29 @@
+{
+ "id" : "23a47848-dae8-4bdb-9ac7-851012c5b102",
+ "name" : "0_public_assets",
+ "request" : {
+ "url" : "/0/public/Assets",
+ "method" : "GET"
+ },
+ "response" : {
+ "status" : 200,
+ "bodyFileName" : "0_public_assets-23a47848-dae8-4bdb-9ac7-851012c5b102.json",
+ "headers" : {
+ "Date" : "Mon, 23 May 2022 10:00:43 GMT",
+ "Content-Type" : "application/json",
+ "cache-control" : "public, max-age=1, s-maxage=1",
+ "strict-transport-security" : "max-age=15768000",
+ "referrer-policy" : "strict-origin-when-cross-origin",
+ "Last-Modified" : "Mon, 23 May 2022 10:00:41 GMT",
+ "CF-Cache-Status" : "HIT",
+ "Age" : "0",
+ "Expect-CT" : "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"",
+ "Set-Cookie" : "__cf_bm=iapj4pvCgI5gecM1t0ur_QSguz813VAzrypZYB4pBag-1653300043-0-AY4IaU2BEtA5otAnha2qtjyHYbyCjFGUegriH+w5U1tkjVkv20xwO/dkWgZBAVf5KPaFbKKiIV3ihPMxAadPaHE=; path=/; expires=Mon, 23-May-22 10:30:43 GMT; domain=.kraken.com; HttpOnly; Secure; SameSite=None",
+ "Server" : "cloudflare",
+ "CF-RAY" : "70fcf2391a9474a1-LHR"
+ }
+ },
+ "uuid" : "23a47848-dae8-4bdb-9ac7-851012c5b102",
+ "persistent" : true,
+ "insertionIndex" : 2
+}
\ No newline at end of file
diff --git a/integration-tests/xchange/src/test/resources/mappings/0_public_ticker-9b4fb7b4-081c-4965-beae-7a5d5c9869e9.json b/integration-tests/xchange/src/test/resources/mappings/0_public_ticker-9b4fb7b4-081c-4965-beae-7a5d5c9869e9.json
new file mode 100644
index 0000000000..699133df24
--- /dev/null
+++ b/integration-tests/xchange/src/test/resources/mappings/0_public_ticker-9b4fb7b4-081c-4965-beae-7a5d5c9869e9.json
@@ -0,0 +1,29 @@
+{
+ "id" : "9b4fb7b4-081c-4965-beae-7a5d5c9869e9",
+ "name" : "0_public_ticker",
+ "request" : {
+ "url" : "/0/public/Ticker?pair=XBTUSDT",
+ "method" : "GET"
+ },
+ "response" : {
+ "status" : 200,
+ "body" : "{\"error\":[],\"result\":{\"XBTUSDT\":{\"a\":[\"30443.10000\",\"1\",\"1.000\"],\"b\":[\"30436.80000\",\"1\",\"1.000\"],\"c\":[\"30441.60000\",\"0.01527161\"],\"v\":[\"129.93859286\",\"366.00353540\"],\"p\":[\"30294.71427\",\"30159.21029\"],\"t\":[933,2587],\"l\":[\"30086.60000\",\"29666.00000\"],\"h\":[\"30647.30000\",\"30647.30000\"],\"o\":\"30295.80000\"}}}",
+ "headers" : {
+ "Date" : "Mon, 23 May 2022 10:00:43 GMT",
+ "Content-Type" : "application/json; charset=utf-8",
+ "cache-control" : "public,max-age=1,smaxage=1",
+ "strict-transport-security" : "max-age=15768000",
+ "vary" : "Accept-Encoding",
+ "referrer-policy" : "strict-origin-when-cross-origin",
+ "Last-Modified" : "Mon, 23 May 2022 10:00:43 GMT",
+ "CF-Cache-Status" : "HIT",
+ "Expect-CT" : "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"",
+ "Set-Cookie" : "__cf_bm=gLPf8Sa5HYkWhYf2CfUzvT_3e6mvdich03g9uw5OfKU-1653300043-0-AX8lXDNJ1hqkGEC8pKIAZURGxJJEtc12pP+QNJ7yO4WIaZNAgXZ3zax7K4M9jdnIkIWBOwIIKJlB/Unne5Yvbqo=; path=/; expires=Mon, 23-May-22 10:30:43 GMT; domain=.kraken.com; HttpOnly; Secure; SameSite=None",
+ "Server" : "cloudflare",
+ "CF-RAY" : "70fcf2398b1274a1-LHR"
+ }
+ },
+ "uuid" : "9b4fb7b4-081c-4965-beae-7a5d5c9869e9",
+ "persistent" : true,
+ "insertionIndex" : 3
+}
\ No newline at end of file
diff --git a/integration-tests/xchange/src/test/resources/mappings/api_v3_exchangeinfo-41fc7d67-259d-4bf2-944d-8a00f9c2370a.json b/integration-tests/xchange/src/test/resources/mappings/api_v3_exchangeinfo-41fc7d67-259d-4bf2-944d-8a00f9c2370a.json
new file mode 100644
index 0000000000..1ce189b7ca
--- /dev/null
+++ b/integration-tests/xchange/src/test/resources/mappings/api_v3_exchangeinfo-41fc7d67-259d-4bf2-944d-8a00f9c2370a.json
@@ -0,0 +1,38 @@
+{
+ "id" : "41fc7d67-259d-4bf2-944d-8a00f9c2370a",
+ "name" : "api_v3_exchangeinfo",
+ "request" : {
+ "url" : "/api/v3/exchangeInfo",
+ "method" : "GET"
+ },
+ "response" : {
+ "status" : 200,
+ "bodyFileName" : "api_v3_exchangeinfo-41fc7d67-259d-4bf2-944d-8a00f9c2370a.json",
+ "headers" : {
+ "Content-Type" : "application/json;charset=UTF-8",
+ "Date" : "Mon, 23 May 2022 10:00:40 GMT",
+ "Server" : "nginx",
+ "Vary" : "Accept-Encoding",
+ "x-mbx-uuid" : "820c2377-8d1c-4f8b-aa84-4d952fb43379",
+ "x-mbx-used-weight" : "10",
+ "x-mbx-used-weight-1m" : "10",
+ "Strict-Transport-Security" : "max-age=31536000; includeSubdomains",
+ "X-Frame-Options" : "SAMEORIGIN",
+ "X-Xss-Protection" : "1; mode=block",
+ "X-Content-Type-Options" : "nosniff",
+ "Content-Security-Policy" : "default-src 'self'",
+ "X-Content-Security-Policy" : "default-src 'self'",
+ "X-WebKit-CSP" : "default-src 'self'",
+ "Cache-Control" : "no-cache, no-store, must-revalidate",
+ "Pragma" : "no-cache",
+ "Expires" : "0",
+ "X-Cache" : "Miss from cloudfront",
+ "Via" : "1.1 dcf307cd37f9d94bc0225628c89153d8.cloudfront.net (CloudFront)",
+ "X-Amz-Cf-Pop" : "LHR61-P4",
+ "X-Amz-Cf-Id" : "1jMJrXKrUkmHDYVgnmxAvRnAgZeE9ChlUE71MD5j19znjm9ahuwHBw=="
+ }
+ },
+ "uuid" : "41fc7d67-259d-4bf2-944d-8a00f9c2370a",
+ "persistent" : true,
+ "insertionIndex" : 1
+}
\ No newline at end of file
diff --git a/integration-tests/xchange/src/test/resources/mappings/api_v3_ticker_24hr-32b9aee3-92c1-45ac-af48-7fd4b7f67da9.json b/integration-tests/xchange/src/test/resources/mappings/api_v3_ticker_24hr-32b9aee3-92c1-45ac-af48-7fd4b7f67da9.json
new file mode 100644
index 0000000000..3c601a5444
--- /dev/null
+++ b/integration-tests/xchange/src/test/resources/mappings/api_v3_ticker_24hr-32b9aee3-92c1-45ac-af48-7fd4b7f67da9.json
@@ -0,0 +1,38 @@
+{
+ "id" : "32b9aee3-92c1-45ac-af48-7fd4b7f67da9",
+ "name" : "api_v3_ticker_24hr",
+ "request" : {
+ "url" : "/api/v3/ticker/24hr?symbol=BTCUSDT",
+ "method" : "GET"
+ },
+ "response" : {
+ "status" : 200,
+ "body" : "{\"symbol\":\"BTCUSDT\",\"priceChange\":\"263.37000000\",\"priceChangePercent\":\"0.873\",\"weightedAvgPrice\":\"30178.56459959\",\"prevClosePrice\":\"30177.32000000\",\"lastPrice\":\"30440.70000000\",\"lastQty\":\"0.00536000\",\"bidPrice\":\"30440.69000000\",\"bidQty\":\"6.00464000\",\"askPrice\":\"30440.70000000\",\"askQty\":\"0.00004000\",\"openPrice\":\"30177.33000000\",\"highPrice\":\"30670.51000000\",\"lowPrice\":\"29668.51000000\",\"volume\":\"41775.05738000\",\"quot [...]
+ "headers" : {
+ "Content-Type" : "application/json;charset=UTF-8",
+ "Date" : "Mon, 23 May 2022 10:00:43 GMT",
+ "Server" : "nginx",
+ "Vary" : "Accept-Encoding",
+ "x-mbx-uuid" : "cd2079da-d451-4253-bebb-d549b3ae623e",
+ "x-mbx-used-weight" : "11",
+ "x-mbx-used-weight-1m" : "11",
+ "Strict-Transport-Security" : "max-age=31536000; includeSubdomains",
+ "X-Frame-Options" : "SAMEORIGIN",
+ "X-Xss-Protection" : "1; mode=block",
+ "X-Content-Type-Options" : "nosniff",
+ "Content-Security-Policy" : "default-src 'self'",
+ "X-Content-Security-Policy" : "default-src 'self'",
+ "X-WebKit-CSP" : "default-src 'self'",
+ "Cache-Control" : "no-cache, no-store, must-revalidate",
+ "Pragma" : "no-cache",
+ "Expires" : "0",
+ "X-Cache" : "Miss from cloudfront",
+ "Via" : "1.1 dcf307cd37f9d94bc0225628c89153d8.cloudfront.net (CloudFront)",
+ "X-Amz-Cf-Pop" : "LHR61-P4",
+ "X-Amz-Cf-Id" : "rkdJI-EMurvz1Duuki0lRXs0n3QIFw_C9U0cK-BC-4AHgOEw67T2Kw=="
+ }
+ },
+ "uuid" : "32b9aee3-92c1-45ac-af48-7fd4b7f67da9",
+ "persistent" : true,
+ "insertionIndex" : 2
+}
\ No newline at end of file