From cb664741dd930583931d44d980f77f5b17a762bf Mon Sep 17 00:00:00 2001 From: RehanRaza Date: Wed, 12 Feb 2020 15:13:49 +0100 Subject: [PATCH] Add unit tests for SdncOscA1Client Change-Id: Icb62bdf45cea91cbf609647c3953304edb7296d6 Issue-ID: NONRTRIC-126 Signed-off-by: RehanRaza --- .../policyagent/clients/SdncOscA1Client.java | 74 ++++--- .../policyagent/clients/SdncOscAdapterInput.java | 38 ++++ .../oransc/policyagent/clients/A1ClientHelper.java | 85 ++++++++ .../policyagent/clients/SdncOscA1ClientTest.java | 236 +++++++++++++++++++++ 4 files changed, 404 insertions(+), 29 deletions(-) create mode 100644 policy-agent/src/main/java/org/oransc/policyagent/clients/SdncOscAdapterInput.java create mode 100644 policy-agent/src/test/java/org/oransc/policyagent/clients/A1ClientHelper.java create mode 100644 policy-agent/src/test/java/org/oransc/policyagent/clients/SdncOscA1ClientTest.java diff --git a/policy-agent/src/main/java/org/oransc/policyagent/clients/SdncOscA1Client.java b/policy-agent/src/main/java/org/oransc/policyagent/clients/SdncOscA1Client.java index ff6e8573..993088aa 100644 --- a/policy-agent/src/main/java/org/oransc/policyagent/clients/SdncOscA1Client.java +++ b/policy-agent/src/main/java/org/oransc/policyagent/clients/SdncOscA1Client.java @@ -20,6 +20,10 @@ package org.oransc.policyagent.clients; +import com.google.gson.FieldNamingPolicy; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + import java.lang.invoke.MethodHandles; import java.util.ArrayList; import java.util.List; @@ -38,27 +42,35 @@ import reactor.core.publisher.Mono; public class SdncOscA1Client implements A1Client { private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - private String a1ControllerBaseUrl; - private String a1ControllerUsername; - private String a1ControllerPassword; + private final String a1ControllerUsername; + private final String a1ControllerPassword; private final RicConfig ricConfig; private final AsyncRestClient restClient; + private static Gson gson = new GsonBuilder() // + .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_DASHES) // + .create(); // + public SdncOscA1Client(RicConfig ricConfig, String baseUrl, String username, String password) { + this(ricConfig, username, password, new AsyncRestClient(baseUrl + "/restconf/operations")); + if (logger.isDebugEnabled()) { + logger.debug("SdncOscA1Client for ric: {}, a1ControllerBaseUrl: {}", ricConfig.name(), baseUrl); + } + } + + public SdncOscA1Client(RicConfig ricConfig, String username, String password, AsyncRestClient restClient) { this.ricConfig = ricConfig; - this.a1ControllerBaseUrl = baseUrl; this.a1ControllerUsername = username; this.a1ControllerPassword = password; - this.restClient = new AsyncRestClient(a1ControllerBaseUrl + "/restconf/operations"); - logger.debug("SdncOscA1Client for ric: {}, a1ControllerBaseUrl: {}", this.ricConfig.name(), - a1ControllerBaseUrl); + this.restClient = restClient; } @Override public Mono> getPolicyTypeIdentities() { - JSONObject paramsJson = new JSONObject(); - paramsJson.put("near-rt-ric-url", ricConfig.baseUrl()); - String inputJsonString = createInputJsonString(paramsJson); + SdncOscAdapterInput inputParams = ImmutableSdncOscAdapterInput.builder() // + .nearRtRicUrl(ricConfig.baseUrl()) // + .build(); + String inputJsonString = createInputJsonString(gson.toJson(inputParams)); logger.debug("POST getPolicyTypeIdentities inputJsonString = {}", inputJsonString); return restClient @@ -70,9 +82,10 @@ public class SdncOscA1Client implements A1Client { @Override public Mono> getPolicyIdentities() { - JSONObject paramsJson = new JSONObject(); - paramsJson.put("near-rt-ric-url", ricConfig.baseUrl()); - String inputJsonString = createInputJsonString(paramsJson); + SdncOscAdapterInput inputParams = ImmutableSdncOscAdapterInput.builder() // + .nearRtRicUrl(ricConfig.baseUrl()) // + .build(); + String inputJsonString = createInputJsonString(gson.toJson(inputParams)); logger.debug("POST getPolicyIdentities inputJsonString = {}", inputJsonString); return restClient @@ -84,10 +97,11 @@ public class SdncOscA1Client implements A1Client { @Override public Mono getPolicyTypeSchema(String policyTypeId) { - JSONObject paramsJson = new JSONObject(); - paramsJson.put("near-rt-ric-url", ricConfig.baseUrl()); - paramsJson.put("policy-type-id", policyTypeId); - String inputJsonString = createInputJsonString(paramsJson); + SdncOscAdapterInput inputParams = ImmutableSdncOscAdapterInput.builder() // + .nearRtRicUrl(ricConfig.baseUrl()) // + .policyTypeId(policyTypeId) // + .build(); + String inputJsonString = createInputJsonString(gson.toJson(inputParams)); logger.debug("POST getPolicyType inputJsonString = {}", inputJsonString); return restClient @@ -99,12 +113,13 @@ public class SdncOscA1Client implements A1Client { @Override public Mono putPolicy(Policy policy) { - JSONObject paramsJson = new JSONObject(); - paramsJson.put("near-rt-ric-url", ricConfig.baseUrl()); - paramsJson.put("policy-id", policy.id()); - paramsJson.put("policy-type-id", policy.type().name()); - paramsJson.put("policy", policy.json()); - String inputJsonString = createInputJsonString(paramsJson); + SdncOscAdapterInput inputParams = ImmutableSdncOscAdapterInput.builder() // + .nearRtRicUrl(ricConfig.baseUrl()) // + .policyTypeId(policy.type().name()) // + .policyId(policy.id()) // + .policy(policy.json()) // + .build(); + String inputJsonString = createInputJsonString(gson.toJson(inputParams)); logger.debug("POST putPolicy inputJsonString = {}", inputJsonString); return restClient @@ -127,10 +142,11 @@ public class SdncOscA1Client implements A1Client { } public Mono deletePolicy(String policyId) { - JSONObject paramsJson = new JSONObject(); - paramsJson.put("near-rt-ric-url", ricConfig.baseUrl()); - paramsJson.put("policy-id", policyId); - String inputJsonString = createInputJsonString(paramsJson); + SdncOscAdapterInput inputParams = ImmutableSdncOscAdapterInput.builder() // + .nearRtRicUrl(ricConfig.baseUrl()) // + .policyId(policyId) // + .build(); + String inputJsonString = createInputJsonString(gson.toJson(inputParams)); logger.debug("POST deletePolicy inputJsonString = {}", inputJsonString); return restClient.postWithAuthHeader("/A1-ADAPTER-API:deletePolicy", inputJsonString, a1ControllerUsername, @@ -143,9 +159,9 @@ public class SdncOscA1Client implements A1Client { .flatMap(x -> Mono.just(A1ProtocolType.SDNC_OSC)); } - private String createInputJsonString(JSONObject paramsJson) { + private String createInputJsonString(String paramsJson) { JSONObject inputJson = new JSONObject(); - inputJson.put("input", paramsJson); + inputJson.put("input", new JSONObject(paramsJson)); return inputJson.toString(); } diff --git a/policy-agent/src/main/java/org/oransc/policyagent/clients/SdncOscAdapterInput.java b/policy-agent/src/main/java/org/oransc/policyagent/clients/SdncOscAdapterInput.java new file mode 100644 index 00000000..9a67f44d --- /dev/null +++ b/policy-agent/src/main/java/org/oransc/policyagent/clients/SdncOscAdapterInput.java @@ -0,0 +1,38 @@ +/*- + * ========================LICENSE_START================================= + * O-RAN-SC + * %% + * Copyright (C) 2020 Nordix Foundation + * %% + * Licensed 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. + * ========================LICENSE_END=================================== + */ + +package org.oransc.policyagent.clients; + +import java.util.Optional; + +import org.immutables.gson.Gson; +import org.immutables.value.Value; + +@Value.Immutable +@Gson.TypeAdapters +public interface SdncOscAdapterInput { + public String nearRtRicUrl(); + + public Optional policyTypeId(); + + public Optional policyId(); + + public Optional policy(); +} diff --git a/policy-agent/src/test/java/org/oransc/policyagent/clients/A1ClientHelper.java b/policy-agent/src/test/java/org/oransc/policyagent/clients/A1ClientHelper.java new file mode 100644 index 00000000..e0f885d4 --- /dev/null +++ b/policy-agent/src/test/java/org/oransc/policyagent/clients/A1ClientHelper.java @@ -0,0 +1,85 @@ +/*- + * ========================LICENSE_START================================= + * O-RAN-SC + * %% + * Copyright (C) 2020 Nordix Foundation + * %% + * Licensed 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. + * ========================LICENSE_END=================================== + */ + +package org.oransc.policyagent.clients; + +import com.google.gson.FieldNamingPolicy; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import java.util.Arrays; +import java.util.Vector; + +import org.json.JSONObject; +import org.oransc.policyagent.configuration.ImmutableRicConfig; +import org.oransc.policyagent.configuration.RicConfig; +import org.oransc.policyagent.repository.ImmutablePolicy; +import org.oransc.policyagent.repository.ImmutablePolicyType; +import org.oransc.policyagent.repository.Policy; +import org.oransc.policyagent.repository.PolicyType; +import org.oransc.policyagent.repository.Ric; +import reactor.core.publisher.Mono; + +public class A1ClientHelper { + private static Gson gson = new GsonBuilder() // + .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_DASHES) // + .create(); // + + private A1ClientHelper() { + } + + protected static String createInputJsonString(SdncOscAdapterInput inputParams) { + JSONObject inputJson = new JSONObject(); + inputJson.put("input", new JSONObject(gson.toJson(inputParams))); + return inputJson.toString(); + } + + protected static Mono createOutputJsonResponse(String key, String value) { + JSONObject paramsJson = new JSONObject(); + paramsJson.put(key, value); + JSONObject responseJson = new JSONObject(); + responseJson.put("output", paramsJson); + return Mono.just(responseJson.toString()); + } + + protected static Ric createRic(String url) { + RicConfig cfg = ImmutableRicConfig.builder().name("ric") // + .baseUrl(url) // + .managedElementIds(new Vector(Arrays.asList("kista_1", "kista_2"))) // + .build(); + return new Ric(cfg); + } + + protected static Policy createPolicy(String nearRtRicUrl, String policyId, String json, String type) { + return ImmutablePolicy.builder() // + .id(policyId) // + .json(json) // + .ownerServiceName("service") // + .ric(createRic(nearRtRicUrl)) // + .type(createPolicyType(type)) // + .lastModified("now") // + .build(); + } + + protected static PolicyType createPolicyType(String name) { + return ImmutablePolicyType.builder().name(name).schema("schema").build(); + } + +} diff --git a/policy-agent/src/test/java/org/oransc/policyagent/clients/SdncOscA1ClientTest.java b/policy-agent/src/test/java/org/oransc/policyagent/clients/SdncOscA1ClientTest.java new file mode 100644 index 00000000..57d809e3 --- /dev/null +++ b/policy-agent/src/test/java/org/oransc/policyagent/clients/SdncOscA1ClientTest.java @@ -0,0 +1,236 @@ +/*- + * ========================LICENSE_START================================= + * O-RAN-SC + * %% + * Copyright (C) 2020 Nordix Foundation + * %% + * Licensed 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. + * ========================LICENSE_END=================================== + */ + +package org.oransc.policyagent.clients; + +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Arrays; +import java.util.List; + +import org.json.JSONException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.stubbing.OngoingStubbing; + +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import reactor.test.StepVerifier; + +@ExtendWith(MockitoExtension.class) +public class SdncOscA1ClientTest { + private static final String CONTROLLER_USERNAME = "username"; + private static final String CONTROLLER_PASSWORD = "password"; + private static final String RIC_1_URL = "RicUrl"; + private static final String POLICYTYPES_IDENTITIES_URL = "/A1-ADAPTER-API:getPolicyTypeIdentities"; + private static final String POLICIES_IDENTITIES_URL = "/A1-ADAPTER-API:getPolicyIdentities"; + private static final String POLICYTYPES_URL = "/A1-ADAPTER-API:getPolicyType"; + private static final String PUT_POLICY_URL = "/A1-ADAPTER-API:putPolicy"; + private static final String DELETE_POLICY_URL = "/A1-ADAPTER-API:deletePolicy"; + + private static final String POLICY_TYPE_1_ID = "type1"; + private static final String POLICY_TYPE_2_ID = "type2"; + private static final String POLICY_TYPE_SCHEMA_VALID = "{\"type\":\"type1\"}"; + private static final String POLICY_TYPE_SCHEMA_INVALID = "\"type\":\"type1\"}"; + private static final String POLICY_1_ID = "policy1"; + private static final String POLICY_2_ID = "policy2"; + private static final String POLICY_JSON_VALID = "{\"scope\":{\"ueId\":\"ue1\"}}"; + private static final String POLICY_JSON_INVALID = "\"scope\":{\"ueId\":\"ue1\"}}"; + + SdncOscA1Client clientUnderTest; + + AsyncRestClient asyncRestClientMock; + + @BeforeEach + public void init() { + asyncRestClientMock = mock(AsyncRestClient.class); + clientUnderTest = new SdncOscA1Client(A1ClientHelper.createRic(RIC_1_URL).getConfig(), CONTROLLER_USERNAME, + CONTROLLER_PASSWORD, asyncRestClientMock); + } + + @Test + public void testGetPolicyTypeIdentities() { + SdncOscAdapterInput inputParams = ImmutableSdncOscAdapterInput.builder() // + .nearRtRicUrl(RIC_1_URL) // + .build(); + String inputJsonString = A1ClientHelper.createInputJsonString(inputParams); + + List policyTypeIds = Arrays.asList(POLICY_TYPE_1_ID, POLICY_TYPE_2_ID); + Mono policyTypeIdsResp = + A1ClientHelper.createOutputJsonResponse("policy-type-id-list", policyTypeIds.toString()); + whenAsyncPostThenReturn(policyTypeIdsResp); + + Mono> returnedMono = clientUnderTest.getPolicyTypeIdentities(); + verify(asyncRestClientMock).postWithAuthHeader(POLICYTYPES_IDENTITIES_URL, inputJsonString, CONTROLLER_USERNAME, + CONTROLLER_PASSWORD); + StepVerifier.create(returnedMono).expectNext(policyTypeIds).expectComplete().verify(); + } + + @Test + public void testGetPolicyIdentities() { + SdncOscAdapterInput inputParams = ImmutableSdncOscAdapterInput.builder() // + .nearRtRicUrl(RIC_1_URL) // + .build(); + String inputJsonString = A1ClientHelper.createInputJsonString(inputParams); + + List policyIds = Arrays.asList(POLICY_1_ID, POLICY_2_ID); + Mono policyIdsResp = A1ClientHelper.createOutputJsonResponse("policy-id-list", policyIds.toString()); + whenAsyncPostThenReturn(policyIdsResp); + + Mono> returnedMono = clientUnderTest.getPolicyIdentities(); + verify(asyncRestClientMock).postWithAuthHeader(POLICIES_IDENTITIES_URL, inputJsonString, CONTROLLER_USERNAME, + CONTROLLER_PASSWORD); + StepVerifier.create(returnedMono).expectNext(policyIds).expectComplete().verify(); + } + + @Test + public void testGetValidPolicyType() { + SdncOscAdapterInput inputParams = ImmutableSdncOscAdapterInput.builder() // + .nearRtRicUrl(RIC_1_URL) // + .policyTypeId(POLICY_TYPE_1_ID) // + .build(); + String inputJsonString = A1ClientHelper.createInputJsonString(inputParams); + + String policyType = "{\"policySchema\": " + POLICY_TYPE_SCHEMA_VALID + ", \"statusSchema\": {} }"; + Mono policyTypeResp = A1ClientHelper.createOutputJsonResponse("policy-type", policyType); + whenAsyncPostThenReturn(policyTypeResp); + + Mono returnedMono = clientUnderTest.getPolicyTypeSchema(POLICY_TYPE_1_ID); + verify(asyncRestClientMock).postWithAuthHeader(POLICYTYPES_URL, inputJsonString, CONTROLLER_USERNAME, + CONTROLLER_PASSWORD); + StepVerifier.create(returnedMono).expectNext(POLICY_TYPE_SCHEMA_VALID).expectComplete().verify(); + } + + @Test + public void testGetInvalidPolicyType() { + SdncOscAdapterInput inputParams = ImmutableSdncOscAdapterInput.builder() // + .nearRtRicUrl(RIC_1_URL) // + .policyTypeId(POLICY_TYPE_1_ID) // + .build(); + String inputJsonString = A1ClientHelper.createInputJsonString(inputParams); + + String policyType = "{\"policySchema\": " + POLICY_TYPE_SCHEMA_INVALID + ", \"statusSchema\": {} }"; + Mono policyTypeResp = A1ClientHelper.createOutputJsonResponse("policy-type", policyType); + whenAsyncPostThenReturn(policyTypeResp); + + Mono returnedMono = clientUnderTest.getPolicyTypeSchema(POLICY_TYPE_1_ID); + verify(asyncRestClientMock).postWithAuthHeader(POLICYTYPES_URL, inputJsonString, CONTROLLER_USERNAME, + CONTROLLER_PASSWORD); + StepVerifier.create(returnedMono).expectErrorMatches(throwable -> throwable instanceof JSONException).verify(); + } + + @Test + public void testPutPolicyValidResponse() { + SdncOscAdapterInput inputParams = ImmutableSdncOscAdapterInput.builder() // + .nearRtRicUrl(RIC_1_URL) // + .policyTypeId(POLICY_TYPE_1_ID) // + .policyId(POLICY_1_ID) // + .policy(POLICY_JSON_VALID) // + .build(); + String inputJsonString = A1ClientHelper.createInputJsonString(inputParams); + + Mono policyResp = A1ClientHelper.createOutputJsonResponse("returned-policy", POLICY_JSON_VALID); + whenAsyncPostThenReturn(policyResp); + + Mono returnedMono = clientUnderTest + .putPolicy(A1ClientHelper.createPolicy(RIC_1_URL, POLICY_1_ID, POLICY_JSON_VALID, POLICY_TYPE_1_ID)); + verify(asyncRestClientMock).postWithAuthHeader(PUT_POLICY_URL, inputJsonString, CONTROLLER_USERNAME, + CONTROLLER_PASSWORD); + StepVerifier.create(returnedMono).expectNext(POLICY_JSON_VALID).expectComplete().verify(); + } + + @Test + public void testPutPolicyInvalidResponse() { + SdncOscAdapterInput inputParams = ImmutableSdncOscAdapterInput.builder() // + .nearRtRicUrl(RIC_1_URL) // + .policyTypeId(POLICY_TYPE_1_ID) // + .policyId(POLICY_1_ID) // + .policy(POLICY_JSON_VALID) // + .build(); + String inputJsonString = A1ClientHelper.createInputJsonString(inputParams); + + Mono policyResp = A1ClientHelper.createOutputJsonResponse("returned-policy", POLICY_JSON_INVALID); + whenAsyncPostThenReturn(policyResp); + + Mono returnedMono = clientUnderTest + .putPolicy(A1ClientHelper.createPolicy(RIC_1_URL, POLICY_1_ID, POLICY_JSON_VALID, POLICY_TYPE_1_ID)); + verify(asyncRestClientMock).postWithAuthHeader(PUT_POLICY_URL, inputJsonString, CONTROLLER_USERNAME, + CONTROLLER_PASSWORD); + StepVerifier.create(returnedMono).expectErrorMatches(throwable -> throwable instanceof JSONException).verify(); + } + + @Test + public void testDeletePolicy() { + SdncOscAdapterInput inputParams = ImmutableSdncOscAdapterInput.builder() // + .nearRtRicUrl(RIC_1_URL) // + .policyId(POLICY_1_ID) // + .build(); + String inputJsonString = A1ClientHelper.createInputJsonString(inputParams); + + whenAsyncPostThenReturn(Mono.empty()); + + Mono returnedMono = clientUnderTest + .deletePolicy(A1ClientHelper.createPolicy(RIC_1_URL, POLICY_1_ID, POLICY_JSON_VALID, POLICY_TYPE_1_ID)); + verify(asyncRestClientMock).postWithAuthHeader(DELETE_POLICY_URL, inputJsonString, CONTROLLER_USERNAME, + CONTROLLER_PASSWORD); + StepVerifier.create(returnedMono).expectComplete().verify(); + } + + @Test + public void testDeleteAllPolicies() { + SdncOscAdapterInput inputParams = ImmutableSdncOscAdapterInput.builder() // + .nearRtRicUrl(RIC_1_URL) // + .build(); + String inputJsonStringGetIds = A1ClientHelper.createInputJsonString(inputParams); + inputParams = ImmutableSdncOscAdapterInput.builder() // + .nearRtRicUrl(RIC_1_URL) // + .policyId(POLICY_1_ID) // + .build(); + String inputJsonStringDeletePolicy1 = A1ClientHelper.createInputJsonString(inputParams); + inputParams = ImmutableSdncOscAdapterInput.builder() // + .nearRtRicUrl(RIC_1_URL) // + .policyId(POLICY_2_ID) // + .build(); + String inputJsonStringDeletePolicy2 = A1ClientHelper.createInputJsonString(inputParams); + + List policyIds = Arrays.asList(POLICY_1_ID, POLICY_2_ID); + Mono policyIdsResp = A1ClientHelper.createOutputJsonResponse("policy-id-list", policyIds.toString()); + whenAsyncPostThenReturn(policyIdsResp).thenReturn(Mono.empty()); + + Flux returnedFlux = clientUnderTest.deleteAllPolicies(); + StepVerifier.create(returnedFlux).expectComplete().verify(); + verify(asyncRestClientMock).postWithAuthHeader(POLICIES_IDENTITIES_URL, inputJsonStringGetIds, + CONTROLLER_USERNAME, CONTROLLER_PASSWORD); + verify(asyncRestClientMock).postWithAuthHeader(DELETE_POLICY_URL, inputJsonStringDeletePolicy1, + CONTROLLER_USERNAME, CONTROLLER_PASSWORD); + verify(asyncRestClientMock).postWithAuthHeader(DELETE_POLICY_URL, inputJsonStringDeletePolicy2, + CONTROLLER_USERNAME, CONTROLLER_PASSWORD); + } + + private OngoingStubbing> whenAsyncPostThenReturn(Mono response) { + return when(asyncRestClientMock.postWithAuthHeader(anyString(), anyString(), anyString(), anyString())) + .thenReturn(response); + } +} -- 2.16.6