diff --git a/qqq-backend-module-api/pom.xml b/qqq-backend-module-api/pom.xml
index f86fb9d8..e390f623 100644
--- a/qqq-backend-module-api/pom.xml
+++ b/qqq-backend-module-api/pom.xml
@@ -34,10 +34,6 @@
-
-
- 0.00
- 0.00
diff --git a/qqq-backend-module-api/src/main/java/com/kingsrook/qqq/backend/module/api/actions/BaseAPIActionUtil.java b/qqq-backend-module-api/src/main/java/com/kingsrook/qqq/backend/module/api/actions/BaseAPIActionUtil.java
index d8ecf17a..f3cd1107 100644
--- a/qqq-backend-module-api/src/main/java/com/kingsrook/qqq/backend/module/api/actions/BaseAPIActionUtil.java
+++ b/qqq-backend-module-api/src/main/java/com/kingsrook/qqq/backend/module/api/actions/BaseAPIActionUtil.java
@@ -634,7 +634,7 @@ public class BaseAPIActionUtil
request.setEntity(new StringEntity(postBody));
request.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
- HttpResponse response = client.execute(request);
+ HttpResponse response = executeOAuthTokenRequest(client, request);
int statusCode = response.getStatusLine().getStatusCode();
HttpEntity entity = response.getEntity();
String resultString = EntityUtils.toString(entity);
@@ -669,6 +669,16 @@ public class BaseAPIActionUtil
+ /*******************************************************************************
+ ** one-line method, factored out so mock/tests can override
+ *******************************************************************************/
+ protected CloseableHttpResponse executeOAuthTokenRequest(CloseableHttpClient client, HttpPost request) throws IOException
+ {
+ return client.execute(request);
+ }
+
+
+
/*******************************************************************************
** As part of making a request - set up its content-type header.
*******************************************************************************/
@@ -880,7 +890,7 @@ public class BaseAPIActionUtil
LOG.info("POST contents [" + ((HttpPost) request).getEntity().toString() + "]");
}
- try(CloseableHttpResponse response = httpClient.execute(request))
+ try(CloseableHttpResponse response = executeHttpRequest(request, httpClient))
{
QHttpResponse qResponse = new QHttpResponse(response);
@@ -924,7 +934,7 @@ public class BaseAPIActionUtil
rateLimitsCaught++;
if(rateLimitsCaught > getMaxAllowedRateLimitErrors())
{
- LOG.error("Giving up POST to [" + table.getName() + "] after too many rate-limit errors (" + getMaxAllowedRateLimitErrors() + ")");
+ LOG.error("Giving up " + request.getMethod() + " to [" + table.getName() + "] after too many rate-limit errors (" + getMaxAllowedRateLimitErrors() + ")");
throw (new QException(rle));
}
@@ -950,6 +960,16 @@ public class BaseAPIActionUtil
+ /*******************************************************************************
+ ** one-line method, factored out so mock/tests can override
+ *******************************************************************************/
+ protected CloseableHttpResponse executeHttpRequest(HttpRequestBase request, CloseableHttpClient httpClient) throws IOException
+ {
+ return httpClient.execute(request);
+ }
+
+
+
/*******************************************************************************
**
*******************************************************************************/
diff --git a/qqq-backend-module-api/src/test/java/com/kingsrook/qqq/backend/module/api/TestUtils.java b/qqq-backend-module-api/src/test/java/com/kingsrook/qqq/backend/module/api/TestUtils.java
index 1217445b..27a12a55 100644
--- a/qqq-backend-module-api/src/test/java/com/kingsrook/qqq/backend/module/api/TestUtils.java
+++ b/qqq-backend-module-api/src/test/java/com/kingsrook/qqq/backend/module/api/TestUtils.java
@@ -32,6 +32,8 @@ import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeUsage;
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
+import com.kingsrook.qqq.backend.core.modules.backend.implementations.memory.MemoryBackendModule;
+import com.kingsrook.qqq.backend.module.api.mocks.MockApiActionUtils;
import com.kingsrook.qqq.backend.module.api.model.AuthorizationType;
import com.kingsrook.qqq.backend.module.api.model.metadata.APIBackendMetaData;
import com.kingsrook.qqq.backend.module.api.model.metadata.APITableBackendDetails;
@@ -42,7 +44,10 @@ import com.kingsrook.qqq.backend.module.api.model.metadata.APITableBackendDetail
*******************************************************************************/
public class TestUtils
{
+ public static final String MEMORY_BACKEND_NAME = "memory";
public static final String EASYPOST_BACKEND_NAME = "easypost";
+ public static final String MOCK_BACKEND_NAME = "mock";
+ public static final String MOCK_TABLE_NAME = "mock";
@@ -52,14 +57,69 @@ public class TestUtils
public static QInstance defineInstance()
{
QInstance qInstance = new QInstance();
- qInstance.addBackend(defineBackend());
- qInstance.addTable(defineTableEasypostTracker());
qInstance.setAuthentication(defineAuthentication());
+
+ qInstance.addBackend(defineMemoryBackend());
+
+ qInstance.addBackend(defineMockBackend());
+ qInstance.addTable(defineMockTable());
+
+ qInstance.addBackend(defineEasypostBackend());
+ qInstance.addTable(defineTableEasypostTracker());
+
return (qInstance);
}
+ /*******************************************************************************
+ ** Define the in-memory backend used in standard tests
+ *******************************************************************************/
+ public static QBackendMetaData defineMemoryBackend()
+ {
+ return new QBackendMetaData()
+ .withName(MEMORY_BACKEND_NAME)
+ .withBackendType(MemoryBackendModule.class);
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ private static QBackendMetaData defineMockBackend()
+ {
+ return (new APIBackendMetaData()
+ .withName(MOCK_BACKEND_NAME)
+ .withAuthorizationType(AuthorizationType.API_KEY_HEADER)
+ .withBaseUrl("http://localhost:9999/mock")
+ .withContentType("application/json")
+ .withActionUtil(new QCodeReference(MockApiActionUtils.class, QCodeUsage.CUSTOMIZER))
+ );
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ private static QTableMetaData defineMockTable()
+ {
+ return (new QTableMetaData()
+ .withName(MOCK_TABLE_NAME)
+ .withBackendName(MOCK_BACKEND_NAME)
+ .withField(new QFieldMetaData("id", QFieldType.STRING))
+ .withField(new QFieldMetaData("name", QFieldType.STRING))
+ .withPrimaryKeyField("id")
+ .withBackendDetails(new APITableBackendDetails()
+ .withTablePath("mock")
+ .withTableWrapperObjectName("mocks")
+ )
+ );
+ }
+
+
+
/*******************************************************************************
** Define the authentication used in standard tests - using 'mock' type.
**
@@ -76,7 +136,7 @@ public class TestUtils
/*******************************************************************************
**
*******************************************************************************/
- public static QBackendMetaData defineBackend()
+ public static QBackendMetaData defineEasypostBackend()
{
String apiKey = new QMetaDataVariableInterpreter().interpret("${env.EASYPOST_API_KEY}");
diff --git a/qqq-backend-module-api/src/test/java/com/kingsrook/qqq/backend/module/api/actions/BaseAPIActionUtilTest.java b/qqq-backend-module-api/src/test/java/com/kingsrook/qqq/backend/module/api/actions/BaseAPIActionUtilTest.java
new file mode 100644
index 00000000..04275a80
--- /dev/null
+++ b/qqq-backend-module-api/src/test/java/com/kingsrook/qqq/backend/module/api/actions/BaseAPIActionUtilTest.java
@@ -0,0 +1,672 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2023. Kingsrook, LLC
+ * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
+ * contact@kingsrook.com
+ * https://github.com/Kingsrook/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package com.kingsrook.qqq.backend.module.api.actions;
+
+
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+import java.util.List;
+import java.util.Map;
+import com.kingsrook.qqq.backend.core.actions.tables.CountAction;
+import com.kingsrook.qqq.backend.core.actions.tables.GetAction;
+import com.kingsrook.qqq.backend.core.actions.tables.InsertAction;
+import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
+import com.kingsrook.qqq.backend.core.actions.tables.UpdateAction;
+import com.kingsrook.qqq.backend.core.context.QContext;
+import com.kingsrook.qqq.backend.core.exceptions.QException;
+import com.kingsrook.qqq.backend.core.model.actions.tables.count.CountInput;
+import com.kingsrook.qqq.backend.core.model.actions.tables.count.CountOutput;
+import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetInput;
+import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetOutput;
+import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput;
+import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertOutput;
+import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryInput;
+import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryOutput;
+import com.kingsrook.qqq.backend.core.model.actions.tables.update.UpdateInput;
+import com.kingsrook.qqq.backend.core.model.actions.tables.update.UpdateOutput;
+import com.kingsrook.qqq.backend.core.model.data.QRecord;
+import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
+import com.kingsrook.qqq.backend.core.model.metadata.tables.UniqueKey;
+import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
+import com.kingsrook.qqq.backend.module.api.BaseTest;
+import com.kingsrook.qqq.backend.module.api.TestUtils;
+import com.kingsrook.qqq.backend.module.api.exceptions.RateLimitException;
+import com.kingsrook.qqq.backend.module.api.mocks.MockApiActionUtils;
+import com.kingsrook.qqq.backend.module.api.mocks.MockApiUtilsHelper;
+import com.kingsrook.qqq.backend.module.api.model.AuthorizationType;
+import com.kingsrook.qqq.backend.module.api.model.OutboundAPILog;
+import com.kingsrook.qqq.backend.module.api.model.OutboundAPILogMetaDataProvider;
+import com.kingsrook.qqq.backend.module.api.model.metadata.APIBackendMetaData;
+import org.apache.http.Header;
+import org.json.JSONArray;
+import org.json.JSONObject;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+
+/*******************************************************************************
+ ** Unit test for com.kingsrook.qqq.backend.module.api.actions.BaseAPIActionUtil
+ *******************************************************************************/
+class BaseAPIActionUtilTest extends BaseTest
+{
+ private static MockApiUtilsHelper mockApiUtilsHelper = new MockApiUtilsHelper();
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @BeforeEach
+ void beforeEach()
+ {
+ mockApiUtilsHelper = new MockApiUtilsHelper();
+ mockApiUtilsHelper.setUseMock(true);
+ MockApiActionUtils.mockApiUtilsHelper = mockApiUtilsHelper;
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Test
+ void testCount() throws QException
+ {
+ mockApiUtilsHelper.enqueueMockResponse("""
+ [
+ {"id": 1, "name": "Homer"},
+ {"id": 2, "name": "Marge"},
+ {"id": 3, "name": "Bart"},
+ {"id": 4, "name": "Lisa"},
+ {"id": 5, "name": "Maggie"}
+ ]
+ """);
+
+ CountInput countInput = new CountInput();
+ countInput.setTableName(TestUtils.MOCK_TABLE_NAME);
+ CountOutput countOutput = new CountAction().execute(countInput);
+ assertEquals(5, countOutput.getCount());
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Test
+ void testCountError() throws QException
+ {
+ ////////////////////////////////////////
+ // avoid the fully mocked makeRequest //
+ ////////////////////////////////////////
+ mockApiUtilsHelper.setUseMock(false);
+ mockApiUtilsHelper.enqueueMockResponse(new QHttpResponse().withStatusCode(500).withContent("""
+ {"error": "Server error"}
+ """));
+
+ CountInput countInput = new CountInput();
+ countInput.setTableName(TestUtils.MOCK_TABLE_NAME);
+ assertThatThrownBy(() -> new CountAction().execute(countInput)).hasRootCauseInstanceOf(Exception.class);
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Test
+ void testGet() throws QException
+ {
+ mockApiUtilsHelper.enqueueMockResponse("""
+ {"id": 3, "name": "Bart"},
+ """);
+
+ GetInput getInput = new GetInput();
+ getInput.setTableName(TestUtils.MOCK_TABLE_NAME);
+ getInput.setPrimaryKey(3);
+ GetOutput getOutput = new GetAction().execute(getInput);
+ assertEquals(3, getOutput.getRecord().getValueInteger("id"));
+ assertEquals("Bart", getOutput.getRecord().getValueString("name"));
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Test
+ void testGetByKey() throws QException
+ {
+ QContext.getQInstance().getTable(TestUtils.MOCK_TABLE_NAME).withUniqueKey(new UniqueKey("id"));
+
+ mockApiUtilsHelper.enqueueMockResponse("""
+ {"id": 3, "name": "Bart"},
+ """);
+
+ GetInput getInput = new GetInput();
+ getInput.setTableName(TestUtils.MOCK_TABLE_NAME);
+ getInput.setUniqueKey(Map.of("id", 3));
+ GetOutput getOutput = new GetAction().execute(getInput);
+ assertEquals(3, getOutput.getRecord().getValueInteger("id"));
+ assertEquals("Bart", getOutput.getRecord().getValueString("name"));
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Test
+ void testQuery() throws QException
+ {
+ mockApiUtilsHelper.enqueueMockResponse("""
+ [
+ {"id": 1, "name": "Homer"},
+ {"id": 2, "name": "Marge"},
+ {"id": 3, "name": "Bart"},
+ {"id": 4, "name": "Lisa"},
+ {"id": 5, "name": "Maggie"}
+ ]
+ """);
+
+ QueryInput queryInput = new QueryInput();
+ queryInput.setTableName(TestUtils.MOCK_TABLE_NAME);
+ QueryOutput queryOutput = new QueryAction().execute(queryInput);
+ assertEquals(5, queryOutput.getRecords().size());
+ assertEquals(1, queryOutput.getRecords().get(0).getValueInteger("id"));
+ assertEquals("Homer", queryOutput.getRecords().get(0).getValueString("name"));
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Test
+ void testQueryObjectWrappingList() throws QException
+ {
+ mockApiUtilsHelper.enqueueMockResponse("""
+ {"mocks": [
+ {"id": 1, "name": "Homer"},
+ {"id": 2, "name": "Marge"},
+ {"id": 3, "name": "Bart"},
+ {"id": 4, "name": "Lisa"},
+ {"id": 5, "name": "Maggie"}
+ ]}
+ """);
+
+ QueryInput queryInput = new QueryInput();
+ queryInput.setTableName(TestUtils.MOCK_TABLE_NAME);
+ QueryOutput queryOutput = new QueryAction().execute(queryInput);
+ assertEquals(5, queryOutput.getRecords().size());
+ assertEquals(1, queryOutput.getRecords().get(0).getValueInteger("id"));
+ assertEquals("Homer", queryOutput.getRecords().get(0).getValueString("name"));
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Test
+ void testQueryObjectWrappingSingleObject() throws QException
+ {
+ mockApiUtilsHelper.enqueueMockResponse("""
+ {"mocks":
+ {"id": 1, "name": "Homer"}
+ }
+ """);
+
+ QueryInput queryInput = new QueryInput();
+ queryInput.setTableName(TestUtils.MOCK_TABLE_NAME);
+ QueryOutput queryOutput = new QueryAction().execute(queryInput);
+ assertEquals(1, queryOutput.getRecords().size());
+ assertEquals(1, queryOutput.getRecords().get(0).getValueInteger("id"));
+ assertEquals("Homer", queryOutput.getRecords().get(0).getValueString("name"));
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Test
+ void testQueryPaginate() throws QException
+ {
+ String oneObject = """
+ {"id": 1, "name": "Homer"}
+ """;
+ StringBuilder response = new StringBuilder("[");
+ for(int i = 0; i < 19; i++)
+ {
+ response.append(oneObject).append(",");
+ }
+ response.append(oneObject);
+ response.append("]");
+ mockApiUtilsHelper.enqueueMockResponse(response.toString());
+ mockApiUtilsHelper.enqueueMockResponse(response.toString());
+ mockApiUtilsHelper.enqueueMockResponse(response.toString());
+ mockApiUtilsHelper.enqueueMockResponse("[]");
+
+ QueryInput queryInput = new QueryInput();
+ queryInput.setTableName(TestUtils.MOCK_TABLE_NAME);
+ QueryOutput queryOutput = new QueryAction().execute(queryInput);
+ assertEquals(60, queryOutput.getRecords().size());
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Test
+ void testQueryError() throws QException
+ {
+ ////////////////////////////////////////
+ // avoid the fully mocked makeRequest //
+ ////////////////////////////////////////
+ mockApiUtilsHelper.setUseMock(false);
+ mockApiUtilsHelper.enqueueMockResponse(new QHttpResponse().withStatusCode(500).withContent("""
+ {"error": "Server error"}
+ """));
+
+ QueryInput queryInput = new QueryInput();
+ queryInput.setTableName(TestUtils.MOCK_TABLE_NAME);
+ assertThatThrownBy(() -> new QueryAction().execute(queryInput)).hasRootCauseInstanceOf(Exception.class);
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Test
+ void testInsert() throws QException
+ {
+ mockApiUtilsHelper.enqueueMockResponse("""
+ {"id": 6}
+ """);
+
+ InsertInput insertInput = new InsertInput();
+ insertInput.setTableName(TestUtils.MOCK_TABLE_NAME);
+ insertInput.setRecords(List.of(new QRecord().withValue("name", "Milhouse")));
+ InsertOutput insertOutput = new InsertAction().execute(insertInput);
+ assertEquals(6, insertOutput.getRecords().get(0).getValueInteger("id"));
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Test
+ void testInsertEmptyInputList() throws QException
+ {
+ InsertInput insertInput = new InsertInput();
+ insertInput.setTableName(TestUtils.MOCK_TABLE_NAME);
+ insertInput.setRecords(List.of());
+ InsertOutput insertOutput = new InsertAction().execute(insertInput);
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Test
+ void testInsertError() throws QException
+ {
+ ////////////////////////////////////////
+ // avoid the fully mocked makeRequest //
+ ////////////////////////////////////////
+ mockApiUtilsHelper.setUseMock(false);
+ mockApiUtilsHelper.enqueueMockResponse(new QHttpResponse().withStatusCode(500).withContent("""
+ {"error": "Server error"}
+ """));
+
+ InsertInput insertInput = new InsertInput();
+ insertInput.setRecords(List.of(new QRecord().withValue("name", "Milhouse")));
+ insertInput.setTableName(TestUtils.MOCK_TABLE_NAME);
+ InsertOutput insertOutput = new InsertAction().execute(insertInput);
+ assertTrue(CollectionUtils.nullSafeHasContents(insertOutput.getRecords().get(0).getErrors()));
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Test
+ void testUpdate() throws QException
+ {
+ mockApiUtilsHelper.enqueueMockResponse("");
+
+ mockApiUtilsHelper.setMockRequestAsserter(httpRequestBase ->
+ {
+ String requestBody = MockApiUtilsHelper.readRequestBody(httpRequestBase);
+ JSONObject requestObject = new JSONObject(requestBody);
+
+ JSONArray mocks = requestObject.getJSONArray("mocks");
+ JSONObject record = mocks.getJSONObject(0);
+
+ assertEquals("Bartholomew", record.getString("name"));
+ assertEquals(3, record.getInt("id"));
+ });
+
+ UpdateInput updateInput = new UpdateInput();
+ updateInput.setTableName(TestUtils.MOCK_TABLE_NAME);
+ updateInput.setRecords(List.of(new QRecord().withValue("id", "3").withValue("name", "Bartholomew")));
+ UpdateOutput updateOutput = new UpdateAction().execute(updateInput);
+
+ // not sure what to assert in here...
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Test
+ void testUpdateEmptyInputList() throws QException
+ {
+ UpdateInput updateInput = new UpdateInput();
+ updateInput.setTableName(TestUtils.MOCK_TABLE_NAME);
+ updateInput.setRecords(List.of());
+ UpdateOutput updateOutput = new UpdateAction().execute(updateInput);
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Test
+ void testUpdateError() throws QException
+ {
+ ////////////////////////////////////////
+ // avoid the fully mocked makeRequest //
+ ////////////////////////////////////////
+ mockApiUtilsHelper.setUseMock(false);
+ mockApiUtilsHelper.enqueueMockResponse(new QHttpResponse().withStatusCode(500).withContent("""
+ {"error": "Server error"}
+ """));
+
+ UpdateInput updateInput = new UpdateInput();
+ updateInput.setRecords(List.of(new QRecord().withValue("name", "Milhouse")));
+ updateInput.setTableName(TestUtils.MOCK_TABLE_NAME);
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // note - right now this is inconsistent with insertAction (and rdbms update), //
+ // where errors are placed in the records, rather than thrown... //
+ /////////////////////////////////////////////////////////////////////////////////
+ assertThatThrownBy(() -> new UpdateAction().execute(updateInput)).hasRootCauseInstanceOf(Exception.class);
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Test
+ void testMakeRequest() throws QException
+ {
+ ////////////////////////////////////////////////////////////////////////////////////////////
+ // this will make it not use the mock makeRequest method, //
+ // but instead the mock executeHttpRequest, so we can test code from the base makeRequest //
+ ////////////////////////////////////////////////////////////////////////////////////////////
+ mockApiUtilsHelper.setUseMock(false);
+ mockApiUtilsHelper.enqueueMockResponse("""
+ {"id": 3, "name": "Bart"},
+ """);
+
+ GetInput getInput = new GetInput();
+ getInput.setTableName(TestUtils.MOCK_TABLE_NAME);
+ getInput.setPrimaryKey(3);
+ GetOutput getOutput = new GetAction().execute(getInput);
+ assertEquals(3, getOutput.getRecord().getValueInteger("id"));
+ assertEquals("Bart", getOutput.getRecord().getValueString("name"));
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Test
+ void test429Then200() throws QException
+ {
+ ////////////////////////////////////////////////////////////////////////////////////////////
+ // this will make it not use the mock makeRequest method, //
+ // but instead the mock executeHttpRequest, so we can test code from the base makeRequest //
+ // specifically, that we can get one 429, and then eventually a 200 //
+ ////////////////////////////////////////////////////////////////////////////////////////////
+ mockApiUtilsHelper.setUseMock(false);
+ mockApiUtilsHelper.enqueueMockResponse(new QHttpResponse().withStatusCode(429).withContent("Try again"));
+ mockApiUtilsHelper.enqueueMockResponse("""
+ {"id": 3, "name": "Bart"},
+ """);
+
+ GetInput getInput = new GetInput();
+ getInput.setTableName(TestUtils.MOCK_TABLE_NAME);
+ getInput.setPrimaryKey(3);
+ GetOutput getOutput = new GetAction().execute(getInput);
+ assertEquals(3, getOutput.getRecord().getValueInteger("id"));
+ assertEquals("Bart", getOutput.getRecord().getValueString("name"));
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Test
+ void testTooMany429() throws QException
+ {
+ ////////////////////////////////////////////////////////////////////////////////////////////
+ // this will make it not use the mock makeRequest method, //
+ // but instead the mock executeHttpRequest, so we can test code from the base makeRequest //
+ // specifically, that after too many 429's we get an error //
+ ////////////////////////////////////////////////////////////////////////////////////////////
+ mockApiUtilsHelper.setUseMock(false);
+ mockApiUtilsHelper.enqueueMockResponse(new QHttpResponse().withStatusCode(429).withContent("Try again"));
+ mockApiUtilsHelper.enqueueMockResponse(new QHttpResponse().withStatusCode(429).withContent("Try again"));
+ mockApiUtilsHelper.enqueueMockResponse(new QHttpResponse().withStatusCode(429).withContent("Try again"));
+ mockApiUtilsHelper.enqueueMockResponse(new QHttpResponse().withStatusCode(429).withContent("Try again"));
+
+ GetInput getInput = new GetInput();
+ getInput.setTableName(TestUtils.MOCK_TABLE_NAME);
+ getInput.setPrimaryKey(3);
+
+ assertThatThrownBy(() -> new GetAction().execute(getInput)).hasRootCauseInstanceOf(RateLimitException.class);
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Test
+ void testApiLogs() throws QException
+ {
+ QInstance qInstance = QContext.getQInstance();
+ OutboundAPILogMetaDataProvider.defineAll(qInstance, TestUtils.MEMORY_BACKEND_NAME, null);
+
+ mockApiUtilsHelper.setUseMock(false);
+ mockApiUtilsHelper.enqueueMockResponse("""
+ {"id": 6}
+ """);
+
+ InsertInput insertInput = new InsertInput();
+ insertInput.setTableName(TestUtils.MOCK_TABLE_NAME);
+ insertInput.setRecords(List.of(new QRecord().withValue("name", "Milhouse")));
+ InsertOutput insertOutput = new InsertAction().execute(insertInput);
+ assertEquals(6, insertOutput.getRecords().get(0).getValueInteger("id"));
+
+ QueryInput queryInput = new QueryInput();
+ queryInput.setTableName(OutboundAPILog.TABLE_NAME);
+ QueryOutput apiLogRecords = new QueryAction().execute(queryInput);
+ assertEquals(1, apiLogRecords.getRecords().size());
+ assertEquals("POST", apiLogRecords.getRecords().get(0).getValueString("method"));
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Test
+ void testBasicAuthApiKey() throws QException
+ {
+ APIBackendMetaData backend = (APIBackendMetaData) QContext.getQInstance().getBackend(TestUtils.MOCK_BACKEND_NAME);
+ backend.setAuthorizationType(AuthorizationType.BASIC_AUTH_API_KEY);
+ backend.setApiKey("9876-WXYZ");
+
+ ////////////////////////////////////////////////////////////////////////////////////////////
+ // this will make it not use the mock makeRequest method, //
+ // but instead the mock executeHttpRequest, so we can test code from the base makeRequest //
+ ////////////////////////////////////////////////////////////////////////////////////////////
+ mockApiUtilsHelper.setUseMock(false);
+ mockApiUtilsHelper.enqueueMockResponse("""
+ {"id": 3, "name": "Bart"},
+ """);
+
+ mockApiUtilsHelper.setMockRequestAsserter(request ->
+ {
+ Header authHeader = request.getFirstHeader("Authorization");
+ assertTrue(authHeader.getValue().startsWith("Basic "));
+ String apiKey = new String(Base64.getDecoder().decode(authHeader.getValue().replace("Basic ", "")), StandardCharsets.UTF_8);
+ assertEquals("9876-WXYZ", apiKey);
+ });
+
+ runSimpleGetAction();
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Test
+ void testBasicAuthUsernamePassword() throws QException
+ {
+ APIBackendMetaData backend = (APIBackendMetaData) QContext.getQInstance().getBackend(TestUtils.MOCK_BACKEND_NAME);
+ backend.setAuthorizationType(AuthorizationType.BASIC_AUTH_USERNAME_PASSWORD);
+ backend.setUsername("god");
+ backend.setPassword("5fingers");
+
+ ////////////////////////////////////////////////////////////////////////////////////////////
+ // this will make it not use the mock makeRequest method, //
+ // but instead the mock executeHttpRequest, so we can test code from the base makeRequest //
+ ////////////////////////////////////////////////////////////////////////////////////////////
+ mockApiUtilsHelper.setUseMock(false);
+ mockApiUtilsHelper.enqueueMockResponse("""
+ {"id": 3, "name": "Bart"},
+ """);
+
+ mockApiUtilsHelper.setMockRequestAsserter(request ->
+ {
+ Header authHeader = request.getFirstHeader("Authorization");
+ assertTrue(authHeader.getValue().startsWith("Basic "));
+ String usernamePassword = new String(Base64.getDecoder().decode(authHeader.getValue().replace("Basic ", "")), StandardCharsets.UTF_8);
+ assertEquals("god:5fingers", usernamePassword);
+ });
+
+ runSimpleGetAction();
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Test
+ void testOAuth2ValidToken() throws QException
+ {
+ APIBackendMetaData backend = (APIBackendMetaData) QContext.getQInstance().getBackend(TestUtils.MOCK_BACKEND_NAME);
+ backend.setAuthorizationType(AuthorizationType.OAUTH2);
+ backend.withCustomValue("accessToken", "validToken");
+
+ ////////////////////////////////////////////////////////////////////////////////////////////
+ // this will make it not use the mock makeRequest method, //
+ // but instead the mock executeHttpRequest, so we can test code from the base makeRequest //
+ ////////////////////////////////////////////////////////////////////////////////////////////
+ mockApiUtilsHelper.setUseMock(false);
+ mockApiUtilsHelper.enqueueMockResponse("""
+ {"id": 3, "name": "Bart"},
+ """);
+
+ mockApiUtilsHelper.setMockRequestAsserter(request ->
+ {
+ Header authHeader = request.getFirstHeader("Authorization");
+ assertTrue(authHeader.getValue().startsWith("Bearer "));
+ String token = authHeader.getValue().replace("Bearer ", "");
+ assertEquals("validToken", token);
+ });
+
+ runSimpleGetAction();
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Test
+ void testOAuth2NullToken() throws QException
+ {
+ APIBackendMetaData backend = (APIBackendMetaData) QContext.getQInstance().getBackend(TestUtils.MOCK_BACKEND_NAME);
+ backend.setAuthorizationType(AuthorizationType.OAUTH2);
+
+ ////////////////////////////////////////////////////////////////////////////////////////////
+ // this will make it not use the mock makeRequest method, //
+ // but instead the mock executeHttpRequest, so we can test code from the base makeRequest //
+ ////////////////////////////////////////////////////////////////////////////////////////////
+ mockApiUtilsHelper.setUseMock(false);
+ mockApiUtilsHelper.enqueueMockResponse("""
+ {"access_token": "myNewToken"}
+ """);
+ mockApiUtilsHelper.enqueueMockResponse("""
+ {"id": 3, "name": "Bart"},
+ """);
+
+ GetOutput getOutput = runSimpleGetAction();
+ assertEquals(3, getOutput.getRecord().getValueInteger("id"));
+ assertEquals("Bart", getOutput.getRecord().getValueString("name"));
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ private static GetOutput runSimpleGetAction() throws QException
+ {
+ GetInput getInput = new GetInput();
+ getInput.setTableName(TestUtils.MOCK_TABLE_NAME);
+ getInput.setPrimaryKey(3);
+ return (new GetAction().execute(getInput));
+ }
+
+}
\ No newline at end of file
diff --git a/qqq-backend-module-api/src/test/java/com/kingsrook/qqq/backend/module/api/mocks/MockApiActionUtils.java b/qqq-backend-module-api/src/test/java/com/kingsrook/qqq/backend/module/api/mocks/MockApiActionUtils.java
new file mode 100644
index 00000000..b54f37d7
--- /dev/null
+++ b/qqq-backend-module-api/src/test/java/com/kingsrook/qqq/backend/module/api/mocks/MockApiActionUtils.java
@@ -0,0 +1,108 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2023. Kingsrook, LLC
+ * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
+ * contact@kingsrook.com
+ * https://github.com/Kingsrook/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package com.kingsrook.qqq.backend.module.api.mocks;
+
+
+import java.io.IOException;
+import com.kingsrook.qqq.backend.core.exceptions.QException;
+import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
+import com.kingsrook.qqq.backend.module.api.actions.BaseAPIActionUtil;
+import com.kingsrook.qqq.backend.module.api.actions.QHttpResponse;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.methods.HttpRequestBase;
+import org.apache.http.impl.client.CloseableHttpClient;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public class MockApiActionUtils extends BaseAPIActionUtil
+{
+ public static MockApiUtilsHelper mockApiUtilsHelper;
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public QHttpResponse makeRequest(QTableMetaData table, HttpRequestBase request) throws QException
+ {
+ return (mockApiUtilsHelper.defaultMockMakeRequest(mockApiUtilsHelper, table, request, () -> super.makeRequest(table, request)));
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ protected CloseableHttpResponse executeHttpRequest(HttpRequestBase request, CloseableHttpClient httpClient) throws IOException
+ {
+ runMockAsserter(request);
+ return new MockHttpResponse(mockApiUtilsHelper);
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ private static void runMockAsserter(HttpRequestBase request)
+ {
+ if(mockApiUtilsHelper.getMockRequestAsserter() != null)
+ {
+ try
+ {
+ mockApiUtilsHelper.getMockRequestAsserter().run(request);
+ }
+ catch(Exception e)
+ {
+ throw (new RuntimeException("Error running mock request asserter", e));
+ }
+ }
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ protected CloseableHttpResponse executeOAuthTokenRequest(CloseableHttpClient client, HttpPost request) throws IOException
+ {
+ runMockAsserter(request);
+ return new MockHttpResponse(mockApiUtilsHelper);
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ protected int getInitialRateLimitBackoffMillis()
+ {
+ return (1);
+ }
+
+}
diff --git a/qqq-backend-module-api/src/test/java/com/kingsrook/qqq/backend/module/api/mocks/MockApiUtilsHelper.java b/qqq-backend-module-api/src/test/java/com/kingsrook/qqq/backend/module/api/mocks/MockApiUtilsHelper.java
new file mode 100644
index 00000000..65b973df
--- /dev/null
+++ b/qqq-backend-module-api/src/test/java/com/kingsrook/qqq/backend/module/api/mocks/MockApiUtilsHelper.java
@@ -0,0 +1,226 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2023. Kingsrook, LLC
+ * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
+ * contact@kingsrook.com
+ * https://github.com/Kingsrook/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package com.kingsrook.qqq.backend.module.api.mocks;
+
+
+import java.io.IOException;
+import java.util.ArrayDeque;
+import java.util.Deque;
+import com.kingsrook.qqq.backend.core.exceptions.QException;
+import com.kingsrook.qqq.backend.core.logging.QLogger;
+import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
+import com.kingsrook.qqq.backend.core.utils.StringUtils;
+import com.kingsrook.qqq.backend.core.utils.lambdas.UnsafeConsumer;
+import com.kingsrook.qqq.backend.core.utils.lambdas.UnsafeSupplier;
+import com.kingsrook.qqq.backend.module.api.actions.QHttpResponse;
+import org.apache.commons.io.IOUtils;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.methods.HttpRequestBase;
+import static org.junit.jupiter.api.Assertions.fail;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public class MockApiUtilsHelper
+{
+ private static final QLogger LOG = QLogger.getLogger(MockApiUtilsHelper.class);
+
+ private boolean useMock = true;
+ private Deque mockResponseQueue = new ArrayDeque<>();
+ private UnsafeConsumer mockRequestAsserter = null;
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public void enqueueMockResponse(String json)
+ {
+ mockResponseQueue.addLast(new QHttpResponse()
+ .withStatusCode(200)
+ .withContent(json)
+ );
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public void enqueueMockResponse(QHttpResponse qHttpResponse)
+ {
+ mockResponseQueue.addLast(qHttpResponse);
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public QHttpResponse returnMockResponseFromQueue(HttpRequestBase request) throws QException
+ {
+ if(getMockRequestAsserter() != null)
+ {
+ try
+ {
+ getMockRequestAsserter().run(request);
+ }
+ catch(Exception e)
+ {
+ throw (new QException("Error running mock request asserter", e));
+ }
+ }
+
+ if(mockResponseQueue.isEmpty())
+ {
+ fail("No mock response is in the queue for " + request.getMethod() + " " + request.getURI());
+ }
+
+ LOG.info("Returning mock http response for " + request.getMethod() + " " + request.getURI());
+ return (mockResponseQueue.removeFirst());
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for useMock
+ *******************************************************************************/
+ public boolean getUseMock()
+ {
+ return (this.useMock);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for useMock
+ *******************************************************************************/
+ public void setUseMock(boolean useMock)
+ {
+ this.useMock = useMock;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for useMock
+ *******************************************************************************/
+ public MockApiUtilsHelper withUseMock(boolean useMock)
+ {
+ this.useMock = useMock;
+ return (this);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for mockResponseQueue
+ *******************************************************************************/
+ public Deque getMockResponseQueue()
+ {
+ return (this.mockResponseQueue);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for mockResponseQueue
+ *******************************************************************************/
+ public void setMockResponseQueue(Deque mockResponseQueue)
+ {
+ this.mockResponseQueue = mockResponseQueue;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for mockResponseQueue
+ *******************************************************************************/
+ public MockApiUtilsHelper withMockResponseQueue(Deque mockResponseQueue)
+ {
+ this.mockResponseQueue = mockResponseQueue;
+ return (this);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for mockRequestAsserter
+ *******************************************************************************/
+ public UnsafeConsumer getMockRequestAsserter()
+ {
+ return (this.mockRequestAsserter);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for mockRequestAsserter
+ *******************************************************************************/
+ public void setMockRequestAsserter(UnsafeConsumer mockRequestAsserter)
+ {
+ this.mockRequestAsserter = mockRequestAsserter;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for mockRequestAsserter
+ *******************************************************************************/
+ public MockApiUtilsHelper withMockRequestAsserter(UnsafeConsumer mockRequestAsserter)
+ {
+ this.mockRequestAsserter = mockRequestAsserter;
+ return (this);
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public QHttpResponse defaultMockMakeRequest(MockApiUtilsHelper mockApiUtilsHelper, QTableMetaData table, HttpRequestBase request, UnsafeSupplier superMethod) throws QException
+ {
+ if(!mockApiUtilsHelper.getUseMock())
+ {
+ QHttpResponse superResponse = superMethod.get();
+ System.out.println("== non-mock response content: ==");
+ System.out.println("Code: " + superResponse.getStatusCode());
+ System.out.println(superResponse.getContent());
+ System.out.println("== ==");
+ return (superResponse);
+ }
+
+ return mockApiUtilsHelper.returnMockResponseFromQueue(request);
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @SuppressWarnings("unchecked")
+ public static String readRequestBody(HttpRequestBase request) throws IOException
+ {
+ return (StringUtils.join("\n", IOUtils.readLines(((HttpPost) request).getEntity().getContent())));
+ }
+}
diff --git a/qqq-backend-module-api/src/test/java/com/kingsrook/qqq/backend/module/api/mocks/MockHttpResponse.java b/qqq-backend-module-api/src/test/java/com/kingsrook/qqq/backend/module/api/mocks/MockHttpResponse.java
new file mode 100644
index 00000000..dbc61f69
--- /dev/null
+++ b/qqq-backend-module-api/src/test/java/com/kingsrook/qqq/backend/module/api/mocks/MockHttpResponse.java
@@ -0,0 +1,302 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2023. Kingsrook, LLC
+ * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
+ * contact@kingsrook.com
+ * https://github.com/Kingsrook/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package com.kingsrook.qqq.backend.module.api.mocks;
+
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.Locale;
+import com.kingsrook.qqq.backend.module.api.actions.QHttpResponse;
+import org.apache.http.Header;
+import org.apache.http.HeaderIterator;
+import org.apache.http.HttpEntity;
+import org.apache.http.ProtocolVersion;
+import org.apache.http.StatusLine;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.entity.BasicHttpEntity;
+import org.apache.http.message.BasicStatusLine;
+import org.apache.http.params.HttpParams;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public class MockHttpResponse implements CloseableHttpResponse
+{
+ private final MockApiUtilsHelper mockApiUtilsHelper;
+
+
+
+ /*******************************************************************************
+ ** Constructor
+ **
+ *******************************************************************************/
+ public MockHttpResponse(MockApiUtilsHelper mockApiUtilsHelper)
+ {
+ this.mockApiUtilsHelper = mockApiUtilsHelper;
+ }
+
+
+
+ @Override
+ public void close() throws IOException
+ {
+
+ }
+
+
+
+ @Override
+ public StatusLine getStatusLine()
+ {
+ ProtocolVersion protocolVersion = new ProtocolVersion("HTTP", 1, 1);
+
+ if(!mockApiUtilsHelper.getMockResponseQueue().isEmpty())
+ {
+ QHttpResponse qHttpResponse = mockApiUtilsHelper.getMockResponseQueue().peekFirst();
+ return (new BasicStatusLine(protocolVersion, qHttpResponse.getStatusCode(), qHttpResponse.getStatusReasonPhrase()));
+ }
+ else
+ {
+ return (new BasicStatusLine(protocolVersion, 200, "OK"));
+ }
+ }
+
+
+
+ @Override
+ public void setStatusLine(StatusLine statusLine)
+ {
+
+ }
+
+
+
+ @Override
+ public void setStatusLine(ProtocolVersion protocolVersion, int i)
+ {
+
+ }
+
+
+
+ @Override
+ public void setStatusLine(ProtocolVersion protocolVersion, int i, String s)
+ {
+
+ }
+
+
+
+ @Override
+ public void setStatusCode(int i) throws IllegalStateException
+ {
+
+ }
+
+
+
+ @Override
+ public void setReasonPhrase(String s) throws IllegalStateException
+ {
+
+ }
+
+
+
+ @Override
+ public HttpEntity getEntity()
+ {
+ BasicHttpEntity basicHttpEntity = new BasicHttpEntity();
+
+ if(!mockApiUtilsHelper.getMockResponseQueue().isEmpty())
+ {
+ QHttpResponse qHttpResponse = mockApiUtilsHelper.getMockResponseQueue().removeFirst();
+ basicHttpEntity.setContent(new ByteArrayInputStream(qHttpResponse.getContent().getBytes()));
+ }
+ else
+ {
+ basicHttpEntity.setContent(new ByteArrayInputStream("".getBytes()));
+ }
+ return (basicHttpEntity);
+ }
+
+
+
+ @Override
+ public void setEntity(HttpEntity httpEntity)
+ {
+
+ }
+
+
+
+ @Override
+ public Locale getLocale()
+ {
+ return null;
+ }
+
+
+
+ @Override
+ public void setLocale(Locale locale)
+ {
+
+ }
+
+
+
+ @Override
+ public ProtocolVersion getProtocolVersion()
+ {
+ return null;
+ }
+
+
+
+ @Override
+ public boolean containsHeader(String s)
+ {
+ return false;
+ }
+
+
+
+ @Override
+ public Header[] getHeaders(String s)
+ {
+ return new Header[0];
+ }
+
+
+
+ @Override
+ public Header getFirstHeader(String s)
+ {
+ return null;
+ }
+
+
+
+ @Override
+ public Header getLastHeader(String s)
+ {
+ return null;
+ }
+
+
+
+ @Override
+ public Header[] getAllHeaders()
+ {
+ return new Header[0];
+ }
+
+
+
+ @Override
+ public void addHeader(Header header)
+ {
+
+ }
+
+
+
+ @Override
+ public void addHeader(String s, String s1)
+ {
+
+ }
+
+
+
+ @Override
+ public void setHeader(Header header)
+ {
+
+ }
+
+
+
+ @Override
+ public void setHeader(String s, String s1)
+ {
+
+ }
+
+
+
+ @Override
+ public void setHeaders(Header[] headers)
+ {
+
+ }
+
+
+
+ @Override
+ public void removeHeader(Header header)
+ {
+
+ }
+
+
+
+ @Override
+ public void removeHeaders(String s)
+ {
+
+ }
+
+
+
+ @Override
+ public HeaderIterator headerIterator()
+ {
+ return null;
+ }
+
+
+
+ @Override
+ public HeaderIterator headerIterator(String s)
+ {
+ return null;
+ }
+
+
+
+ @Override
+ public HttpParams getParams()
+ {
+ return null;
+ }
+
+
+
+ @Override
+ public void setParams(HttpParams httpParams)
+ {
+
+ }
+}