CAMEL-10857 Make Salesforce integration tests w...

...ork with new Salesforce instance

This changes the way Salesforce environment is setup for integration
tests are, previously one would need to manually configure the instance
while now it is done automatically by using _Salesforce Migration Tool_.

This tool needs to be downloaded from Salesforce[1] and placed in the
`components/camel-salesforce/it/resources/migration-tool/` directory.

Definitions for currently used packaged applications, approval process,
classes, test documents, layouts, field customizations and custom
objects, permission sets, profiles, test reports and tabs are provided.

Also a connected application definition is provided to facilitate the
setup.

Tests were rearranged into two groups, those that can be freely run in
random order and in parallel, and those that need to be run sequentially
and independent of each other (marked with Standalone category).

Tests were refactored to make them more stable and easier to maintain.
Mostly to introduce parallelism in parameterised tests and to perform
proper setup and cleanup (although cleanup is still an issue with some
test).

[1] https://developer.salesforce.com/page/Force.com_Migration_Tool


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/ee55a3bc
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/ee55a3bc
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/ee55a3bc

Branch: refs/heads/master
Commit: ee55a3bc6e04fea54bd30cc1d3926020ea024661
Parents: b877b45
Author: Zoran Regvart <zregv...@apache.org>
Authored: Tue Mar 7 20:14:01 2017 +0100
Committer: Zoran Regvart <zregv...@apache.org>
Committed: Tue Mar 7 21:23:48 2017 +0100

----------------------------------------------------------------------
 .../MerchandiseRestResource.apxc                |  44 --
 .../camel-salesforce-component/README.md        |  26 +
 .../camel-salesforce-component/pom.xml          |  87 ++-
 .../src/main/docs/salesforce-component.adoc     |  18 +-
 .../salesforce/AbstractSalesforceTestBase.java  |   6 -
 .../salesforce/ApprovalIntegrationTest.java     |  49 +-
 .../salesforce/BulkApiIntegrationTest.java      |  20 +-
 .../salesforce/BulkApiJobIntegrationTest.java   | 138 ++--
 .../CompositeApiBatchIntegrationTest.java       | 124 ++-
 .../CompositeApiTreeIntegrationTest.java        |  15 +-
 .../salesforce/RecentIntegrationTest.java       |  53 +-
 .../salesforce/RestApiIntegrationTest.java      | 775 +++++++------------
 ...ceComponentConfigurationIntegrationTest.java |   8 +-
 .../camel/component/salesforce/Standalone.java  |  24 +
 .../salesforce/dto/generated/Task.java          |  55 ++
 .../salesforce/dto/generated/Tasks__c.java      |  45 --
 .../camel-salesforce-maven-plugin/pom.xml       |   4 +
 .../it/resources/migration-tool/.gitignore      |   1 +
 .../salesforce/applications/Warehouse.app       |  27 +
 ...Account.Test_Account_Process.approvalProcess |  44 ++
 .../classes/MerchandiseRestResource.cls         |  60 ++
 .../MerchandiseRestResource.cls-meta.xml        |  21 +
 .../classes/MerchandiseRestResourceTests.cls    |  73 ++
 .../MerchandiseRestResourceTests.cls-meta.xml   |  21 +
 .../salesforce/classes/UpdateProfile.cls        |  37 +
 .../classes/UpdateProfile.cls-meta.xml          |  21 +
 ...CamelSalesforceIntegrationTests.connectedApp |  27 +
 .../documents/Test_Documents-meta.xml           |  22 +
 .../documents/Test_Documents/Test_Document.txt  |  18 +
 .../Test_Documents/Test_Document.txt-meta.xml   |  22 +
 .../layouts/Invoice__c-Invoice Layout.layout    |  86 ++
 .../Line_Item__c-Line Item Layout.layout        |  78 ++
 .../Merchandise__c-Merchandise Layout.layout    | 102 +++
 .../resources/salesforce/objects/Account.object |  30 +
 .../salesforce/objects/Invoice__c.object        | 117 +++
 .../salesforce/objects/Line_Item__c.object      | 112 +++
 .../salesforce/objects/Merchandise__c.object    | 119 +++
 .../it/resources/salesforce/package.xml         |  91 +++
 .../Hard_Delete_Permission_Set.permissionset    |  79 ++
 .../resources/salesforce/profiles/Admin.profile | 628 +++++++++++++++
 .../Analytics Cloud Integration User.profile    | 148 ++++
 .../Analytics Cloud Security User.profile       | 105 +++
 .../profiles/Authenticated Website.profile      | 109 +++
 .../profiles/Chatter External User.profile      | 113 +++
 .../profiles/Chatter Free User.profile          | 137 ++++
 .../profiles/Chatter Moderator User.profile     | 141 ++++
 .../salesforce/profiles/ContractManager.profile | 225 ++++++
 .../profiles/Cross Org Data Proxy User.profile  |  97 +++
 .../Custom%3A Marketing Profile.profile         | 209 +++++
 .../profiles/Custom%3A Sales Profile.profile    | 209 +++++
 .../profiles/Custom%3A Support Profile.profile  | 221 ++++++
 .../Customer Community Login User.profile       | 117 +++
 .../Customer Community Plus Login User.profile  | 129 +++
 .../Customer Community Plus User.profile        | 129 +++
 .../profiles/Customer Community User.profile    | 117 +++
 .../Customer Portal Manager Custom.profile      | 125 +++
 .../Customer Portal Manager Standard.profile    | 125 +++
 .../profiles/External Identity User.profile     | 117 +++
 .../Force%2Ecom - App Subscription User.profile | 197 +++++
 .../profiles/Force%2Ecom - Free User.profile    | 173 +++++
 .../profiles/Gold Partner User.profile          | 141 ++++
 .../High Volume Customer Portal User.profile    | 113 +++
 .../profiles/HighVolumePortal.profile           | 109 +++
 .../salesforce/profiles/Identity User.profile   | 137 ++++
 .../profiles/MarketingProfile.profile           | 233 ++++++
 .../Partner App Subscription User.profile       | 197 +++++
 .../Partner Community Login User.profile        | 137 ++++
 .../profiles/Partner Community User.profile     | 137 ++++
 .../salesforce/profiles/PlatformPortal.profile  | 113 +++
 .../salesforce/profiles/ReadOnly.profile        | 185 +++++
 .../profiles/Silver Partner User.profile        | 121 +++
 .../salesforce/profiles/SolutionManager.profile | 221 ++++++
 .../salesforce/profiles/Standard.profile        | 217 ++++++
 .../salesforce/profiles/StandardAul.profile     | 201 +++++
 ...ystem Administrator With Hard Delete.profile | 624 +++++++++++++++
 .../profiles/Work%2Ecom Only User.profile       | 193 +++++
 .../salesforce/reports/Test_Reports-meta.xml    |  20 +
 .../reports/Test_Reports/Test_Report.report     |  54 ++
 .../it/resources/salesforce/tabs/Invoice__c.tab |  22 +
 .../salesforce/tabs/Merchandise__c.tab          |  22 +
 components/camel-salesforce/pom.xml             |  63 +-
 .../test-salesforce-login.properties.sample     |  70 ++
 82 files changed, 8823 insertions(+), 777 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/ee55a3bc/components/camel-salesforce/camel-salesforce-component/MerchandiseRestResource.apxc
----------------------------------------------------------------------
diff --git 
a/components/camel-salesforce/camel-salesforce-component/MerchandiseRestResource.apxc
 
b/components/camel-salesforce/camel-salesforce-component/MerchandiseRestResource.apxc
deleted file mode 100644
index 91ce5ce..0000000
--- 
a/components/camel-salesforce/camel-salesforce-component/MerchandiseRestResource.apxc
+++ /dev/null
@@ -1,44 +0,0 @@
-@RestResource(urlMapping='/Merchandise/*')
-global with sharing class MerchandiseRestResource {
-
-    @HttpGet
-    global static Merchandise__c doGet() {
-        RestRequest req = RestContext.request;
-        String merchandiseId = null;
-        if (!req.requestURI.endsWith('/')) {
-            merchandiseId = 
req.requestURI.substring(req.requestURI.lastIndexOf('/')+1);
-        } else if (req.params.get('id') != null) {
-            merchandiseId = req.params.get('id');
-        }
-        if (merchandiseId != null) {
-               Merchandise__c merchandise = [SELECT Id, Name, Description__c, 
Price__c, Total_Inventory__c FROM Merchandise__c WHERE Id = :merchandiseId];
-            return merchandise;
-        } else {
-            throw new InvalidParamException('Missing merchandise id in URL and 
query params');
-        }
-    }
-  
-       @HttpPatch
-       global static Merchandise__c doPatch(Merchandise__c merchandise) {
-        // lookup merchandise
-        Merchandise__c current = [SELECT Id, Name, Description__c, Price__c, 
Total_Inventory__c FROM Merchandise__c WHERE Id = :merchandise.Id];
-        if (current == null) {
-            throw new InvalidParamException('Missing merchandise for id ' + 
merchandise.Id);
-        }
-        if (merchandise.Description__c != null) {
-            current.Description__c = merchandise.Description__c;
-        }
-        if (merchandise.Price__c != null) {
-            current.Price__c = merchandise.Price__c;
-        }
-        if (merchandise.Total_Inventory__c != null) {
-            current.Total_Inventory__c = merchandise.Total_Inventory__c;
-        }
-
-        update current;
-        return current;
-    }
-
-       // Invalid Merchandise Id exception
-    public class InvalidParamException extends Exception {}
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/ee55a3bc/components/camel-salesforce/camel-salesforce-component/README.md
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/README.md 
b/components/camel-salesforce/camel-salesforce-component/README.md
index 44285b2..c6387f6 100644
--- a/components/camel-salesforce/camel-salesforce-component/README.md
+++ b/components/camel-salesforce/camel-salesforce-component/README.md
@@ -73,8 +73,34 @@ To subscribe to an existing topic
 
 **Note:** These instructions are only for running integration tests, they use 
permissions and IP restrictions that should be reconsidered for production use. 
 
+**Note:** Running the tests you will quickly use up your API allowance, 15000 
requests/day in the free developer account, make sure that you won't deny your 
other applications/users access by running them.
+
 In order to run the integration tests you need a Salesforce Developer account. 
You can get a Salesforce Developer account by visiting 
[developer.salesforce.com](https://developer.salesforce.com/) and sign up for 
one.
 
+As of 2.19 we maintain any Salesforce setup needed to run the integration 
tests in the `it/resources/salesforce` directory, the files there are generated 
by the _Salesforce Migration Tool_ that you can freely download from [Force.com 
Migration 
Tool](https://developer.salesforce.com/page/Force.com_Migration_Tool). This is 
an Apache Ant extension, by which you get additional Ant tasks to retrieve and 
to upload configuration, classes, schema changes and such. Download it and 
place the `ant-salesforce.jar` from the downloaded ZIP file into 
`components/camel-salesforce/it/resources/migration-tool/`.
+
+We have integrated _Salesforce Migration Tool_ into the Maven 
_integration-test_ lifecycle phase and it should run and update your Salesforce 
instance to a state capable of running integration tests. Start by creating 
`test-salesforce-login.properties` in the parent Maven module 
(`camel-salesforce`), you can use `test-salesforce-login.properties.sample` as 
reference.
+
+**Note:** Remember that if you do not relax IP restrictions, by default you'll 
need to append the security token on the password you place in the 
`test-salesforce-login.properties` file.
+
+Before running the tests for the first time run the migration by invoking 
Maven from the `camel-salesforce-component` Maven module directory:
+
+    $ mvn -Pintegration antrun:run@setup-salesforce-instance
+
+This will create a _Connected App_ with predefined Consumer Key (the one 
mentioned in the comment one in `test-salesforce-login.properties.sample`) and 
a name of `CamelSalesforceIntegrationTests`. After running the migration access 
your Salesforce instance and provide _Consumer Secret_ (`clientSecret`) 
property to `test-salesforce-login.properties.sample`.
+
+This however is run every time when you run the integration tests by issuing 
from the `camel-salesforce-component` Maven module directory:
+
+    $ mvn -Pintegration verify
+
+If you need any custom fields, Apex classes or other configuration changes 
done, make sure to download them using the _Salesforce Migration Tool_ and 
include them in `it/resources/salesforce` directory.
+
+If your tests cannot be run alongside other tests you can use 
`@Category(Standalone.class)` to mark them as such.
+
+#### Manual Salesforce instance setup for integration tests
+
+This is include for those that wish to setup the Salesforce instance manually 
for integration tests.
+
 Besides that account you'll need a _test user_ account that has `Bulk API Hard 
Delete` permission. You can create one by going to _My Developer Account_ (link 
from [developer.salesforce.com](https://login.salesforce.com/?lt=de)). Under 
_Administer_ expand _Manage Users_  and select _Profiles_ find _System 
Administrator_ profile and select _Clone_. Use `System Administrator With Hard 
Delete` as the profile name, and after saving under _Administrative 
Permissions_ click edit and tick _Bulk API Hard Delete_ and save. Next, create 
a new user under _Administer_ expand _Manage Users_  and select _Users_ and 
then click on _New User_. Fill in the required fields, and select _Salesforce_ 
for _User License_ and newly created profile for _Profile_. You get two user 
_Salesforce_ licenses so the newly created user will put you at a maximum.
 
 Install the Warehouse package, tested with _Spring 2013_ (version 1.2) that 
can be installed from the 
[https://login.salesforce.com/packaging/installPackage.apexp?p0=04ti0000000Pj8s](https://login.salesforce.com/packaging/installPackage.apexp?p0=04ti0000000Pj8s),
 and make the following modifications manually:

http://git-wip-us.apache.org/repos/asf/camel/blob/ee55a3bc/components/camel-salesforce/camel-salesforce-component/pom.xml
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/pom.xml 
b/components/camel-salesforce/camel-salesforce-component/pom.xml
index 58f65d2..b920db9 100644
--- a/components/camel-salesforce/camel-salesforce-component/pom.xml
+++ b/components/camel-salesforce/camel-salesforce-component/pom.xml
@@ -15,7 +15,8 @@
   See the License for the specific language governing permissions and
   limitations under the License.
 -->
-<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/maven-v4_0_0.xsd";>
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/maven-v4_0_0.xsd";>
 
   <modelVersion>4.0.0</modelVersion>
 
@@ -37,6 +38,7 @@
     </camel.osgi.export.pkg>
     
<camel.osgi.export.service>org.apache.camel.spi.ComponentResolver;component=salesforce</camel.osgi.export.service>
     
<camel.osgi.private.pkg>org.apache.camel.component.salesforce.internal.*</camel.osgi.private.pkg>
+    <salesforce.component.root>..</salesforce.component.root>
   </properties>
 
   <dependencies>
@@ -113,7 +115,7 @@
       <artifactId>slf4j-api</artifactId>
     </dependency>
 
-    <!-- testing -->  
+    <!-- testing -->
     <dependency>
       <groupId>org.apache.logging.log4j</groupId>
       <artifactId>log4j-api</artifactId>
@@ -162,6 +164,12 @@
       <artifactId>mockito-core</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>com.googlecode.junit-toolbox</groupId>
+      <artifactId>junit-toolbox</artifactId>
+      <version>2.2</version>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <build>
@@ -181,4 +189,79 @@
       </plugin>
     </plugins>
   </build>
+
+  <profiles>
+    <profile>
+      <id>integration</id>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-antrun-plugin</artifactId>
+            <executions>
+              <execution>
+                <id>setup-salesforce-instance</id>
+                <goals>
+                  <goal>run</goal>
+                </goals>
+                <phase>pre-integration-test</phase>
+                <configuration>
+                  <target>
+                    <taskdef resource="com/salesforce/antlib.xml" 
uri="antlib:com.salesforce">
+                      <classpath>
+                        <pathelement 
location="${salesforce.component.root}/it/resources/migration-tool/ant-salesforce.jar"
 />
+                      </classpath>
+                    </taskdef>
+
+                    <property 
file="${salesforce.component.root}/test-salesforce-login.properties" />
+
+                    <sf:deploy xmlns:sf="antlib:com.salesforce" 
username="${userName}" password="${password}"
+                      
deployRoot="${salesforce.component.root}/it/resources/salesforce" 
rollbackOnError="true" />
+                  </target>
+                </configuration>
+              </execution>
+            </executions>
+          </plugin>
+          <plugin>
+            <artifactId>maven-failsafe-plugin</artifactId>
+            <executions>
+              <execution>
+                <phase>integration-test</phase>
+                <goals>
+                  <goal>integration-test</goal>
+                </goals>
+                <configuration>
+                  <childDelegation>false</childDelegation>
+                  <useFile>true</useFile>
+                  <forkCount>3</forkCount>
+                  <runOrder>random</runOrder>
+                  <reuseForks>true</reuseForks>
+                  
<forkedProcessTimeoutInSeconds>300</forkedProcessTimeoutInSeconds>
+                  <includes>
+                    <include>**/*IntegrationTest.java</include>
+                  </includes>
+                  
<excludedGroups>org.apache.camel.component.salesforce.Standalone</excludedGroups>
+                </configuration>
+              </execution>
+              <execution>
+                <id>standalone-integration-tests</id>
+                <phase>integration-test</phase>
+                <goals>
+                  <goal>integration-test</goal>
+                </goals>
+                <configuration>
+                  <childDelegation>false</childDelegation>
+                  <useFile>true</useFile>
+                  <includes>
+                    <include>**/*IntegrationTest.java</include>
+                  </includes>
+                  
<groups>org.apache.camel.component.salesforce.Standalone</groups>
+                </configuration>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
 </project>

http://git-wip-us.apache.org/repos/asf/camel/blob/ee55a3bc/components/camel-salesforce/camel-salesforce-component/src/main/docs/salesforce-component.adoc
----------------------------------------------------------------------
diff --git 
a/components/camel-salesforce/camel-salesforce-component/src/main/docs/salesforce-component.adoc
 
b/components/camel-salesforce/camel-salesforce-component/src/main/docs/salesforce-component.adoc
index 1eb3525..bc396ab 100644
--- 
a/components/camel-salesforce/camel-salesforce-component/src/main/docs/salesforce-component.adoc
+++ 
b/components/camel-salesforce/camel-salesforce-component/src/main/docs/salesforce-component.adoc
@@ -20,6 +20,10 @@ for this component:
 </dependency>
 ------------------------------------------------------------
 
+NOTE: Developers wishing to contribute to the component are instructed
+to look at the README.md file on instructions on how to get started and
+setup your environment for running integration tests.
+
 ### URI format
 
 The URI scheme for a salesforce component is as follows
@@ -427,6 +431,7 @@ The Salesforce component supports 24 options which are 
listed below.
 
 
 
+{% raw %}
 [width="100%",cols="2,1,1m,1m,5",options="header"]
 |=======================================================================
 | Name | Group | Default | Java Type | Description
@@ -455,6 +460,7 @@ The Salesforce component supports 24 options which are 
listed below.
 | packages | common |  | String[] | Package names to scan for DTO classes 
(multiple packages can be separated by comma).
 | resolvePropertyPlaceholders | advanced | true | boolean | Whether the 
component should resolve property placeholders on itself when starting. Only 
properties which are of String type can use property placeholders.
 |=======================================================================
+{% endraw %}
 // component options: END
 
 
@@ -467,23 +473,24 @@ The Salesforce component supports 24 options which are 
listed below.
 
 
 // endpoint options: START
-The Salesforce endpoint is configured using URI syntax:
+The Salesforce component is configured using the URI syntax with the following 
path and query parameters:
 
     salesforce:operationName:topicName
 
-  with the following path and query parameters:
-
-#### Path Parameters (2 parameters):
+#### 2 path parameters:
 
+{% raw %}
 [width="100%",cols="2,1,1m,6",options="header"]
 |=======================================================================
 | Name | Default | Java Type | Description
 | operationName |  | OperationName | The operation to use
 | topicName |  | String | The name of the topic to use
 |=======================================================================
+{% endraw %}
 
-#### Query Parameters (41 parameters):
+#### 41 query parameters:
 
+{% raw %}
 [width="100%",cols="2,1,1m,1m,5",options="header"]
 |=======================================================================
 | Name | Group | Default | Java Type | Description
@@ -529,6 +536,7 @@ The Salesforce endpoint is configured using URI syntax:
 | exchangePattern | consumer (advanced) |  | ExchangePattern | Sets the 
exchange pattern when the consumer creates an exchange.
 | synchronous | advanced | false | boolean | Sets whether synchronous 
processing should be strictly used or Camel is allowed to use asynchronous 
processing (if supported).
 |=======================================================================
+{% endraw %}
 // endpoint options: END
 
 

http://git-wip-us.apache.org/repos/asf/camel/blob/ee55a3bc/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/AbstractSalesforceTestBase.java
----------------------------------------------------------------------
diff --git 
a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/AbstractSalesforceTestBase.java
 
b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/AbstractSalesforceTestBase.java
index 31bf180..7be8404 100644
--- 
a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/AbstractSalesforceTestBase.java
+++ 
b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/AbstractSalesforceTestBase.java
@@ -25,12 +25,6 @@ import org.apache.camel.test.junit4.CamelTestSupport;
 public abstract class AbstractSalesforceTestBase extends CamelTestSupport {
 
     @Override
-    public boolean isCreateCamelContextPerClass() {
-        // only create the context once for this class
-        return true;
-    }
-
-    @Override
     protected RouteBuilder createRouteBuilder() throws Exception {
         // create the test component
         createComponent();

http://git-wip-us.apache.org/repos/asf/camel/blob/ee55a3bc/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/ApprovalIntegrationTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/ApprovalIntegrationTest.java
 
b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/ApprovalIntegrationTest.java
index 47d71d5..789958b 100644
--- 
a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/ApprovalIntegrationTest.java
+++ 
b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/ApprovalIntegrationTest.java
@@ -20,6 +20,8 @@ import java.util.Arrays;
 import java.util.List;
 import java.util.stream.Collectors;
 
+import com.googlecode.junittoolbox.ParallelParameterized;
+
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.salesforce.api.dto.approval.ApprovalRequest;
 import 
org.apache.camel.component.salesforce.api.dto.approval.ApprovalRequest.Action;
@@ -28,10 +30,9 @@ import 
org.apache.camel.component.salesforce.api.dto.approval.Approvals;
 import org.apache.camel.component.salesforce.api.dto.approval.Approvals.Info;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
 import org.junit.runners.Parameterized.Parameters;
 
-@RunWith(Parameterized.class)
+@RunWith(ParallelParameterized.class)
 public class ApprovalIntegrationTest extends AbstractApprovalIntegrationTest {
 
     private final String format;
@@ -41,31 +42,24 @@ public class ApprovalIntegrationTest extends 
AbstractApprovalIntegrationTest {
         this.format = format;
     }
 
-    @Parameters(name = "format = {0}")
-    public static Iterable<String> formats() {
-        return Arrays.asList("JSON", "XML");
-    }
-
     @Test
     public void shouldSubmitAndFetchApprovals() {
         final ApprovalResult approvalResult = template.requestBody(
-                String.format(
-                        "salesforce:approval?"//
-                            + "format=%s"//
-                            + "&approvalActionType=Submit"//
-                            + "&approvalContextId=%s"//
-                            + "&approvalNextApproverIds=%s"//
-                            + "&approvalComments=Integration test"//
-                            + 
"&approvalProcessDefinitionNameOrId=Test_Account_Process",
-                        format, accountIds.get(0), userId),
-                NOT_USED, ApprovalResult.class);
+            String.format("salesforce:approval?"//
+                + "format=%s"//
+                + "&approvalActionType=Submit"//
+                + "&approvalContextId=%s"//
+                + "&approvalNextApproverIds=%s"//
+                + "&approvalComments=Integration test"//
+                + "&approvalProcessDefinitionNameOrId=Test_Account_Process", 
format, accountIds.get(0), userId),
+            NOT_USED, ApprovalResult.class);
 
         assertNotNull("Approval should have resulted in value", 
approvalResult);
 
         assertEquals("There should be one Account waiting approval", 1, 
approvalResult.size());
 
         assertEquals("Instance status of the item in approval result should be 
`Pending`", "Pending",
-                approvalResult.iterator().next().getInstanceStatus());
+            approvalResult.iterator().next().getInstanceStatus());
 
         // as it stands on 18.11.2016. the GET method on 
/vXX.X/process/approvals/ with Accept other than
         // `application/json` results in HTTP status 500, so only JSON is 
supported
@@ -89,15 +83,15 @@ public class ApprovalIntegrationTest extends 
AbstractApprovalIntegrationTest {
         }).collect(Collectors.toList());
 
         final ApprovalResult approvalResult = template.requestBody(
-                String.format("salesforce:approval?"//
-                    + "format=%s"//
-                    + "&approvalActionType=Submit"//
-                    + "&approvalNextApproverIds=%s"//
-                    + 
"&approvalProcessDefinitionNameOrId=Test_Account_Process", format, userId),
-                approvalRequests, ApprovalResult.class);
+            String.format("salesforce:approval?"//
+                + "format=%s"//
+                + "&approvalActionType=Submit"//
+                + "&approvalNextApproverIds=%s"//
+                + "&approvalProcessDefinitionNameOrId=Test_Account_Process", 
format, userId),
+            approvalRequests, ApprovalResult.class);
 
         assertEquals("Should have same number of approval results as 
requests", approvalRequests.size(),
-                approvalResult.size());
+            approvalResult.size());
     }
 
     @Override
@@ -109,4 +103,9 @@ public class ApprovalIntegrationTest extends 
AbstractApprovalIntegrationTest {
         };
     }
 
+    @Parameters(name = "format = {0}")
+    public static Iterable<String> formats() {
+        return Arrays.asList("JSON", "XML");
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/ee55a3bc/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/BulkApiIntegrationTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/BulkApiIntegrationTest.java
 
b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/BulkApiIntegrationTest.java
index 3caab7f..5dbb1c7 100644
--- 
a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/BulkApiIntegrationTest.java
+++ 
b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/BulkApiIntegrationTest.java
@@ -30,29 +30,29 @@ import org.eclipse.jetty.http.HttpMethod;
 import org.eclipse.jetty.http.HttpStatus;
 import org.eclipse.jetty.util.ssl.SslContextFactory;
 import org.junit.Test;
+import org.junit.experimental.categories.Category;
 
+@Category(Standalone.class)
 public class BulkApiIntegrationTest extends AbstractBulkApiTestBase {
 
     @Test
     public void testRetry() throws Exception {
-        SalesforceComponent sf = context().getComponent("salesforce", 
SalesforceComponent.class);
-        String accessToken = sf.getSession().getAccessToken();
+        final SalesforceComponent sf = context().getComponent("salesforce", 
SalesforceComponent.class);
+        final String accessToken = sf.getSession().getAccessToken();
 
-        SslContextFactory sslContextFactory = new SslContextFactory();
+        final SslContextFactory sslContextFactory = new SslContextFactory();
         sslContextFactory.setSslContext(new 
SSLContextParameters().createSSLContext(context));
-        HttpClient httpClient = new HttpClient(sslContextFactory);
+        final HttpClient httpClient = new HttpClient(sslContextFactory);
         httpClient.setConnectTimeout(60000);
         httpClient.start();
 
-        String uri = sf.getLoginConfig().getLoginUrl() + 
"/services/oauth2/revoke?token=" + accessToken;
-        Request logoutGet = httpClient.newRequest(uri)
-            .method(HttpMethod.GET)
-            .timeout(1, TimeUnit.MINUTES);
+        final String uri = sf.getLoginConfig().getLoginUrl() + 
"/services/oauth2/revoke?token=" + accessToken;
+        final Request logoutGet = 
httpClient.newRequest(uri).method(HttpMethod.GET).timeout(1, TimeUnit.MINUTES);
 
-        ContentResponse response = logoutGet.send();
+        final ContentResponse response = logoutGet.send();
         assertEquals(HttpStatus.OK_200, response.getStatus());
 
-        JobInfo jobInfo = new JobInfo();
+        final JobInfo jobInfo = new JobInfo();
         jobInfo.setOperation(OperationEnum.INSERT);
         jobInfo.setContentType(ContentType.CSV);
         jobInfo.setObject(Merchandise__c.class.getSimpleName());

http://git-wip-us.apache.org/repos/asf/camel/blob/ee55a3bc/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/BulkApiJobIntegrationTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/BulkApiJobIntegrationTest.java
 
b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/BulkApiJobIntegrationTest.java
index cd7f39e..84f60ab 100644
--- 
a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/BulkApiJobIntegrationTest.java
+++ 
b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/BulkApiJobIntegrationTest.java
@@ -16,80 +16,44 @@
  */
 package org.apache.camel.component.salesforce;
 
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.stream.Collectors;
+
+import com.googlecode.junittoolbox.ParallelParameterized;
 
 import org.apache.camel.component.salesforce.api.dto.bulk.ContentType;
 import org.apache.camel.component.salesforce.api.dto.bulk.JobInfo;
 import org.apache.camel.component.salesforce.api.dto.bulk.JobStateEnum;
 import org.apache.camel.component.salesforce.api.dto.bulk.OperationEnum;
 import org.apache.camel.component.salesforce.dto.generated.Merchandise__c;
-import org.junit.experimental.theories.DataPoints;
-import org.junit.experimental.theories.Theory;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
 
+@RunWith(ParallelParameterized.class)
 public class BulkApiJobIntegrationTest extends AbstractBulkApiTestBase {
 
-    // test jobs for testJobLifecycle
-    @DataPoints
-    public static JobInfo[] getJobs() {
-        JobInfo jobInfo = new JobInfo();
-
-        // insert XML
-        jobInfo.setObject(Merchandise__c.class.getSimpleName());
-        jobInfo.setContentType(ContentType.XML);
-        jobInfo.setOperation(OperationEnum.INSERT);
-
-        List<JobInfo> result = new ArrayList<JobInfo>();
-        result.add(jobInfo);
-
-        // insert CSV
-        jobInfo = new JobInfo();
-        jobInfo.setObject(Merchandise__c.class.getSimpleName());
-        jobInfo.setContentType(ContentType.CSV);
-        jobInfo.setOperation(OperationEnum.INSERT);
-        result.add(jobInfo);
-
-        // update CSV
-        jobInfo = new JobInfo();
-        jobInfo.setObject(Merchandise__c.class.getSimpleName());
-        jobInfo.setContentType(ContentType.CSV);
-        jobInfo.setOperation(OperationEnum.UPDATE);
-        result.add(jobInfo);
-
-        // upsert CSV
-        jobInfo = new JobInfo();
-        jobInfo.setObject(Merchandise__c.class.getSimpleName());
-        jobInfo.setContentType(ContentType.CSV);
-        jobInfo.setOperation(OperationEnum.UPSERT);
-        jobInfo.setExternalIdFieldName("Name");
-        result.add(jobInfo);
-
-        // delete CSV
-        jobInfo = new JobInfo();
-        jobInfo.setObject(Merchandise__c.class.getSimpleName());
-        jobInfo.setContentType(ContentType.CSV);
-        jobInfo.setOperation(OperationEnum.DELETE);
-        result.add(jobInfo);
+    @Parameter(0)
+    public JobInfo jobInfo;
 
-        // hard delete CSV
-        jobInfo = new JobInfo();
-        jobInfo.setObject(Merchandise__c.class.getSimpleName());
-        jobInfo.setContentType(ContentType.CSV);
-        jobInfo.setOperation(OperationEnum.HARD_DELETE);
-        result.add(jobInfo);
+    @Parameter(1)
+    public String operationName;
 
-        // query CSV
-        jobInfo = new JobInfo();
-        jobInfo.setObject(Merchandise__c.class.getSimpleName());
-        jobInfo.setContentType(ContentType.CSV);
-        jobInfo.setOperation(OperationEnum.QUERY);
-        result.add(jobInfo);
+    @Before
+    public void setupProfileWithHardDelete() throws IOException {
+        final SalesforceLoginConfig loginConfig = 
LoginConfigHelper.getLoginConfig();
 
-        return result.toArray(new JobInfo[result.size()]);
+        template().requestBodyAndHeader(
+            
"salesforce:apexCall/UpdateProfile?apexMethod=PATCH&sObjectClass=java.lang.String",
 null,
+            SalesforceEndpointConfig.APEX_QUERY_PARAM_PREFIX + "username", 
loginConfig.getUserName());
     }
 
-    @Theory
-    public void testJobLifecycle(JobInfo jobInfo) throws Exception {
+    @Test
+    public void testJobLifecycle() throws Exception {
         log.info("Testing Job lifecycle for {} of type {}", 
jobInfo.getOperation(), jobInfo.getContentType());
 
         // test create
@@ -108,4 +72,62 @@ public class BulkApiJobIntegrationTest extends 
AbstractBulkApiTestBase {
         assertSame("Job should be ABORTED", JobStateEnum.ABORTED, 
jobInfo.getState());
     }
 
+    // test jobs for testJobLifecycle
+    @Parameters(name = "operation = {1}")
+    public static Iterable<Object[]> getJobs() {
+        final List<JobInfo> result = new ArrayList<>();
+
+        // insert XML
+        final JobInfo insertXml = new JobInfo();
+        insertXml.setObject(Merchandise__c.class.getSimpleName());
+        insertXml.setContentType(ContentType.XML);
+        insertXml.setOperation(OperationEnum.INSERT);
+        result.add(insertXml);
+
+        // insert CSV
+        JobInfo insertCsv = new JobInfo();
+        insertCsv = new JobInfo();
+        insertCsv.setObject(Merchandise__c.class.getSimpleName());
+        insertCsv.setContentType(ContentType.CSV);
+        insertCsv.setOperation(OperationEnum.INSERT);
+        result.add(insertCsv);
+
+        // update CSV
+        final JobInfo updateCsv = new JobInfo();
+        updateCsv.setObject(Merchandise__c.class.getSimpleName());
+        updateCsv.setContentType(ContentType.CSV);
+        updateCsv.setOperation(OperationEnum.UPDATE);
+        result.add(updateCsv);
+
+        // upsert CSV
+        final JobInfo upsertCsv = new JobInfo();
+        upsertCsv.setObject(Merchandise__c.class.getSimpleName());
+        upsertCsv.setContentType(ContentType.CSV);
+        upsertCsv.setOperation(OperationEnum.UPSERT);
+        upsertCsv.setExternalIdFieldName("Name");
+        result.add(upsertCsv);
+
+        // delete CSV
+        final JobInfo deleteCsv = new JobInfo();
+        deleteCsv.setObject(Merchandise__c.class.getSimpleName());
+        deleteCsv.setContentType(ContentType.CSV);
+        deleteCsv.setOperation(OperationEnum.DELETE);
+        result.add(deleteCsv);
+
+        // hard delete CSV
+        final JobInfo hardDeleteCsv = new JobInfo();
+        hardDeleteCsv.setObject(Merchandise__c.class.getSimpleName());
+        hardDeleteCsv.setContentType(ContentType.CSV);
+        hardDeleteCsv.setOperation(OperationEnum.HARD_DELETE);
+        result.add(hardDeleteCsv);
+
+        // query CSV
+        final JobInfo queryCsv = new JobInfo();
+        queryCsv.setObject(Merchandise__c.class.getSimpleName());
+        queryCsv.setContentType(ContentType.CSV);
+        queryCsv.setOperation(OperationEnum.QUERY);
+        result.add(queryCsv);
+
+        return result.stream().map(j -> new Object[] {j, 
j.getOperation().name()}).collect(Collectors.toList());
+    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/ee55a3bc/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/CompositeApiBatchIntegrationTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/CompositeApiBatchIntegrationTest.java
 
b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/CompositeApiBatchIntegrationTest.java
index 946ba5d..b70b87f 100644
--- 
a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/CompositeApiBatchIntegrationTest.java
+++ 
b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/CompositeApiBatchIntegrationTest.java
@@ -18,11 +18,17 @@ package org.apache.camel.component.salesforce;
 
 import java.io.IOException;
 import java.util.Arrays;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
+import com.googlecode.junittoolbox.ParallelParameterized;
 import com.thoughtworks.xstream.annotations.XStreamImplicit;
 
+import org.apache.camel.CamelExecutionException;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.salesforce.api.dto.AbstractQueryRecordsBase;
 import org.apache.camel.component.salesforce.api.dto.CreateSObjectResult;
@@ -30,15 +36,15 @@ import 
org.apache.camel.component.salesforce.api.dto.composite.SObjectBatch;
 import 
org.apache.camel.component.salesforce.api.dto.composite.SObjectBatch.Method;
 import 
org.apache.camel.component.salesforce.api.dto.composite.SObjectBatchResponse;
 import 
org.apache.camel.component.salesforce.api.dto.composite.SObjectBatchResult;
+import org.apache.camel.component.salesforce.api.utils.Version;
 import org.apache.camel.component.salesforce.dto.generated.Account;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
 import org.junit.runners.Parameterized.Parameters;
 
-@RunWith(Parameterized.class)
+@RunWith(ParallelParameterized.class)
 public class CompositeApiBatchIntegrationTest extends 
AbstractSalesforceTestBase {
 
     public static class Accounts extends AbstractQueryRecordsBase {
@@ -55,24 +61,27 @@ public class CompositeApiBatchIntegrationTest extends 
AbstractSalesforceTestBase
 
     }
 
-    private static final String V34 = "34.0";
+    private static final Set<String> VERSIONS = new HashSet<>(
+        Arrays.asList(SalesforceEndpointConfig.DEFAULT_VERSION, "34.0", 
"36.0", "37.0", "39.0"));
 
     private String accountId;
 
     private final String batchuri;
 
-    public CompositeApiBatchIntegrationTest(final String format) {
-        this.batchuri = "salesforce:composite-batch?format=" + format;
-    }
+    private final String version;
 
-    @Parameters(name = "format = {0}")
-    public static Iterable<String> formats() {
-        return Arrays.asList("JSON", "XML");
+    public CompositeApiBatchIntegrationTest(final String format, final String 
version) {
+        this.version = version;
+        batchuri = "salesforce:composite-batch?format=" + format;
     }
 
     @After
     public void removeRecords() {
-        
template.sendBody("salesforce:deleteSObject?sObjectName=Account&sObjectId=" + 
accountId, null);
+        try {
+            
template.sendBody("salesforce:deleteSObject?sObjectName=Account&sObjectId=" + 
accountId, null);
+        } catch (final CamelExecutionException ignored) {
+            // other tests run in parallel could have deleted the Account
+        }
 
         template.request("direct:deleteBatchAccounts", null);
     }
@@ -90,7 +99,7 @@ public class CompositeApiBatchIntegrationTest extends 
AbstractSalesforceTestBase
 
     @Test
     public void shouldSubmitBatchUsingCompositeApi() {
-        final SObjectBatch batch = new SObjectBatch(V34);
+        final SObjectBatch batch = new SObjectBatch(version);
 
         final Account updates = new Account();
         updates.setName("NewName");
@@ -113,7 +122,7 @@ public class CompositeApiBatchIntegrationTest extends 
AbstractSalesforceTestBase
 
     @Test
     public void shouldSupportGenericBatchRequests() {
-        final SObjectBatch batch = new SObjectBatch(V34);
+        final SObjectBatch batch = new SObjectBatch(version);
 
         batch.addGeneric(Method.GET, "/sobjects/Account/" + accountId);
 
@@ -122,7 +131,7 @@ public class CompositeApiBatchIntegrationTest extends 
AbstractSalesforceTestBase
 
     @Test
     public void shouldSupportLimits() {
-        final SObjectBatch batch = new SObjectBatch(V34);
+        final SObjectBatch batch = new SObjectBatch(version);
 
         batch.addLimits();
 
@@ -147,7 +156,7 @@ public class CompositeApiBatchIntegrationTest extends 
AbstractSalesforceTestBase
 
     @Test
     public void shouldSupportObjectCreation() {
-        final SObjectBatch batch = new SObjectBatch(V34);
+        final SObjectBatch batch = new SObjectBatch(version);
 
         final Account newAccount = new Account();
         newAccount.setName("Account created from Composite batch API");
@@ -171,7 +180,7 @@ public class CompositeApiBatchIntegrationTest extends 
AbstractSalesforceTestBase
 
     @Test
     public void shouldSupportObjectDeletion() {
-        final SObjectBatch batch = new SObjectBatch(V34);
+        final SObjectBatch batch = new SObjectBatch(version);
 
         batch.addDelete("Account", accountId);
 
@@ -180,7 +189,7 @@ public class CompositeApiBatchIntegrationTest extends 
AbstractSalesforceTestBase
 
     @Test
     public void shouldSupportObjectRetrieval() {
-        final SObjectBatch batch = new SObjectBatch(V34);
+        final SObjectBatch batch = new SObjectBatch(version);
 
         batch.addGet("Account", accountId, "Name");
 
@@ -201,7 +210,7 @@ public class CompositeApiBatchIntegrationTest extends 
AbstractSalesforceTestBase
 
     @Test
     public void shouldSupportObjectUpdates() {
-        final SObjectBatch batch = new SObjectBatch(V34);
+        final SObjectBatch batch = new SObjectBatch(version);
 
         final Account updates = new Account();
         updates.setName("NewName");
@@ -213,7 +222,7 @@ public class CompositeApiBatchIntegrationTest extends 
AbstractSalesforceTestBase
 
     @Test
     public void shouldSupportQuery() {
-        final SObjectBatch batch = new SObjectBatch(V34);
+        final SObjectBatch batch = new SObjectBatch(version);
 
         batch.addQuery("SELECT Id, Name FROM Account");
 
@@ -234,7 +243,7 @@ public class CompositeApiBatchIntegrationTest extends 
AbstractSalesforceTestBase
 
     @Test
     public void shouldSupportQueryAll() {
-        final SObjectBatch batch = new SObjectBatch(V34);
+        final SObjectBatch batch = new SObjectBatch(version);
 
         batch.addQueryAll("SELECT Id, Name FROM Account");
 
@@ -255,6 +264,10 @@ public class CompositeApiBatchIntegrationTest extends 
AbstractSalesforceTestBase
 
     @Test
     public void shouldSupportRelatedObjectRetrieval() throws IOException {
+        if (Version.create(version).compareTo(Version.create("36.0")) < 0) {
+            return;
+        }
+
         final SObjectBatch batch = new SObjectBatch("36.0");
 
         batch.addGetRelated("Account", accountId, "CreatedBy");
@@ -278,9 +291,12 @@ public class CompositeApiBatchIntegrationTest extends 
AbstractSalesforceTestBase
 
     @Test
     public void shouldSupportSearch() {
-        final SObjectBatch batch = new SObjectBatch(V34);
+        final SObjectBatch batch = new SObjectBatch(version);
 
-        batch.addSearch("FIND {Batch} IN Name Fields RETURNING Account (Name) 
");
+        // we cannot rely on search returning the `Composite API Batch` 
account as the search indexer runs
+        // asynchronously to object creation, so that account might not be 
indexed at this time, so we search for
+        // `United` Account that should be created with developer instance
+        batch.addSearch("FIND {United} IN Name Fields RETURNING Account 
(Name)");
 
         final SObjectBatchResponse response = testBatch(batch);
 
@@ -289,32 +305,44 @@ public class CompositeApiBatchIntegrationTest extends 
AbstractSalesforceTestBase
 
         final Object firstBatchResult = batchResult.getResult();
 
+        final Object searchResult;
+        if (firstBatchResult instanceof Map) {
+            // the JSON and XML responses differ, XML has a root node which 
can be either SearchResults or
+            // SearchResultWithMetadata
+            // furthermore version 37.0 search results are no longer array, 
but dictionary of {
+            // "searchRecords": [<array>] } and the XML output changed to 
<SearchResultWithMetadata><searchRecords>, so
+            // we have:
+            // @formatter:off
+            // | version | format | response syntax                            
                           |
+            // |    34   |  JSON  | {attributes={type=Account...               
                           |
+            // |    34   |  XML   | 
{SearchResults={attributes={type=Account...                           |
+            // |    37   |  JSON  | 
{searchRecords=[{attributes={type=Account...                          |
+            // |    37   |  XML   | 
{SearchResultWithMetadata={searchRecords={attributes={type=Account... |
+            // @formatter:on
+            @SuppressWarnings("unchecked")
+            final Map<String, Object> tmp = (Map<String, Object>) 
firstBatchResult;
+
+            @SuppressWarnings("unchecked")
+            final Map<String, Object> nested = (Map<String, Object>) 
tmp.getOrDefault("SearchResultWithMetadata", tmp);
+
+            // JSON and XML structure are different, XML has `SearchResults` 
node, JSON does not
+            searchResult = nested.getOrDefault("searchRecords", 
nested.getOrDefault("SearchResults", nested));
+        } else {
+            searchResult = firstBatchResult;
+        }
+
         final Map<String, Object> result;
-        if (firstBatchResult instanceof List) {
+        if (searchResult instanceof List) {
             @SuppressWarnings("unchecked")
-            final Map<String, Object> tmp = (Map<String, Object>) ((List) 
firstBatchResult).get(0);
+            final Map<String, Object> tmp = (Map<String, Object>) ((List) 
searchResult).get(0);
             result = tmp;
         } else {
             @SuppressWarnings("unchecked")
-            final Map<String, Object> tmp = (Map<String, Object>) 
firstBatchResult;
+            final Map<String, Object> tmp = (Map<String, Object>) searchResult;
             result = tmp;
         }
 
-        // JSON and XML structure are different, XML has `SearchResults` node, 
JSON does not
-        @SuppressWarnings("unchecked")
-        final Map<String, String> data = (Map<String, String>) 
result.getOrDefault("SearchResults", result);
-
-        assertNotNull(data.get("Name"));
-    }
-
-    SObjectBatchResponse testBatch(final SObjectBatch batch) {
-        final SObjectBatchResponse response = template.requestBody(batchuri, 
batch, SObjectBatchResponse.class);
-
-        assertNotNull("Response should be provided", response);
-
-        assertFalse("Received errors in: " + response, response.hasErrors());
-
-        return response;
+        assertNotNull(result.get("Name"));
     }
 
     @Override
@@ -333,6 +361,22 @@ public class CompositeApiBatchIntegrationTest extends 
AbstractSalesforceTestBase
 
     @Override
     protected String salesforceApiVersionToUse() {
-        return "37.0";
+        return version;
+    }
+
+    SObjectBatchResponse testBatch(final SObjectBatch batch) {
+        final SObjectBatchResponse response = template.requestBody(batchuri, 
batch, SObjectBatchResponse.class);
+
+        assertNotNull("Response should be provided", response);
+
+        assertFalse("Received errors in: " + response, response.hasErrors());
+
+        return response;
+    }
+
+    @Parameters(name = "format = {0}, version = {1}")
+    public static Iterable<Object[]> formats() {
+        return VERSIONS.stream().flatMap(v -> Stream.of(new Object[] {"JSON", 
v}, new Object[] {"XML", v}))
+            .collect(Collectors.toList());
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/ee55a3bc/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/CompositeApiTreeIntegrationTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/CompositeApiTreeIntegrationTest.java
 
b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/CompositeApiTreeIntegrationTest.java
index cf6fb84..0a73df5 100644
--- 
a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/CompositeApiTreeIntegrationTest.java
+++ 
b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/CompositeApiTreeIntegrationTest.java
@@ -18,6 +18,8 @@ package org.apache.camel.component.salesforce;
 
 import java.util.Arrays;
 
+import com.googlecode.junittoolbox.ParallelParameterized;
+
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.salesforce.api.dto.composite.SObjectTree;
 import org.apache.camel.component.salesforce.dto.generated.Account;
@@ -26,10 +28,9 @@ import 
org.apache.camel.component.salesforce.dto.generated.Asset;
 import org.apache.camel.component.salesforce.dto.generated.Contact;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
 import org.junit.runners.Parameterized.Parameters;
 
-@RunWith(Parameterized.class)
+@RunWith(ParallelParameterized.class)
 public class CompositeApiTreeIntegrationTest extends 
AbstractSalesforceTestBase {
 
     private final String format;
@@ -38,11 +39,6 @@ public class CompositeApiTreeIntegrationTest extends 
AbstractSalesforceTestBase
         this.format = format;
     }
 
-    @Parameters(name = "format = {0}")
-    public static Iterable<String> formats() {
-        return Arrays.asList("JSON", "XML");
-    }
-
     @Test
     public void shouldSubmitTreeUsingCompositeApi() {
         final Account simpleAccount = new Account();
@@ -114,4 +110,9 @@ public class CompositeApiTreeIntegrationTest extends 
AbstractSalesforceTestBase
             }
         };
     }
+
+    @Parameters(name = "format = {0}")
+    public static Iterable<String> formats() {
+        return Arrays.asList("JSON", "XML");
+    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/ee55a3bc/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/RecentIntegrationTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/RecentIntegrationTest.java
 
b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/RecentIntegrationTest.java
index 3774295..8fb5812 100644
--- 
a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/RecentIntegrationTest.java
+++ 
b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/RecentIntegrationTest.java
@@ -29,7 +29,9 @@ import 
org.apache.camel.component.salesforce.dto.generated.Account;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.experimental.categories.Category;
 
+@Category(Standalone.class)
 public class RecentIntegrationTest extends AbstractSalesforceTestBase {
 
     public static class Accounts extends AbstractQueryRecordsBase {
@@ -48,20 +50,6 @@ public class RecentIntegrationTest extends 
AbstractSalesforceTestBase {
 
     private static final Object NOT_USED = null;
 
-    static Account account(final int ord) {
-        final Account account = new Account();
-        account.setName("recent-" + ord);
-
-        return account;
-    }
-
-    static void assertRecentItemsSize(final List<RecentItem> items, final int 
expected) {
-        final List<RecentItem> recentItems = items.stream().filter(i -> 
i.getName().startsWith("recent-"))
-                .collect(Collectors.toList());
-
-        assertListSize("Expected " + expected + " items named `recent-N` in 
recent items", recentItems, expected);
-    }
-
     @After
     public void deleteRecords() {
         template.sendBody("direct:delete-recent", NOT_USED);
@@ -70,7 +58,7 @@ public class RecentIntegrationTest extends 
AbstractSalesforceTestBase {
     @Before
     public void setupTenRecentItems() {
         final List<Account> accounts = IntStream.range(0, 
10).mapToObj(RecentIntegrationTest::account)
-                .collect(Collectors.toList());
+            .collect(Collectors.toList());
 
         template.sendBody("direct:create-recent", accounts);
     }
@@ -87,7 +75,7 @@ public class RecentIntegrationTest extends 
AbstractSalesforceTestBase {
     public void shouldFetchRecentItemsLimitingByHeaderParam() {
         @SuppressWarnings("unchecked")
         final List<RecentItem> items = 
template.requestBody("direct:test-recent-with-header-limit-param", NOT_USED,
-                List.class);
+            List.class);
 
         assertRecentItemsSize(items, 5);
     }
@@ -96,7 +84,7 @@ public class RecentIntegrationTest extends 
AbstractSalesforceTestBase {
     public void shouldFetchRecentItemsLimitingByParamInBody() {
         @SuppressWarnings("unchecked")
         final List<RecentItem> items = 
template.requestBody("direct:test-recent-with-body-limit-param", NOT_USED,
-                List.class);
+            List.class);
 
         assertRecentItemsSize(items, 5);
     }
@@ -105,7 +93,7 @@ public class RecentIntegrationTest extends 
AbstractSalesforceTestBase {
     public void shouldFetchRecentItemsLimitingByUriParam() {
         @SuppressWarnings("unchecked")
         final List<RecentItem> items = 
template.requestBody("direct:test-recent-with-limit-uri-param", NOT_USED,
-                List.class);
+            List.class);
 
         assertRecentItemsSize(items, 5);
     }
@@ -116,25 +104,38 @@ public class RecentIntegrationTest extends 
AbstractSalesforceTestBase {
             @Override
             public void configure() throws Exception {
                 
from("direct:create-recent").split().body().to("salesforce:createSObject?sObjectName=Account").end()
-                        .to("salesforce:query?sObjectClass=" + 
Accounts.class.getName()
-                                + "&sObjectQuery=SELECT Id FROM Account WHERE 
Name LIKE 'recent-%' FOR VIEW");
+                    .to("salesforce:query?sObjectClass=" + 
Accounts.class.getName()
+                        + "&sObjectQuery=SELECT Id FROM Account WHERE Name 
LIKE 'recent-%' FOR VIEW");
 
                 from("direct:delete-recent")
-                        .to("salesforce:query?sObjectClass=" + 
Accounts.class.getName()
-                                + "&sObjectQuery=SELECT Id FROM Account WHERE 
Name LIKE 'recent-%'")
-                        .transform(simple("${body.records}")).split().body()
-                        
.setHeader(SalesforceEndpointConfig.SOBJECT_ID).simple("${body.id}")
-                        .to("salesforce:deleteSObject?sObjectName=Account");
+                    .to("salesforce:query?sObjectClass=" + 
Accounts.class.getName()
+                        + "&sObjectQuery=SELECT Id FROM Account WHERE Name 
LIKE 'recent-%'")
+                    
.transform(simple("${body.records}")).split().body().setHeader(SalesforceEndpointConfig.SOBJECT_ID)
+                    
.simple("${body.id}").to("salesforce:deleteSObject?sObjectName=Account");
 
                 from("direct:test-recent").to("salesforce:recent");
 
                 
from("direct:test-recent-with-limit-uri-param").to("salesforce:recent?limit=5");
 
                 
from("direct:test-recent-with-header-limit-param").setHeader(SalesforceEndpointConfig.LIMIT).constant(5)
-                        .to("salesforce:recent");
+                    .to("salesforce:recent");
 
                 
from("direct:test-recent-with-body-limit-param").setBody(constant(5)).to("salesforce:recent");
             }
         };
     }
+
+    static Account account(final int ord) {
+        final Account account = new Account();
+        account.setName("recent-" + ord);
+
+        return account;
+    }
+
+    static void assertRecentItemsSize(final List<RecentItem> items, final int 
expected) {
+        final List<RecentItem> recentItems = items.stream().filter(i -> 
i.getName().startsWith("recent-"))
+            .collect(Collectors.toList());
+
+        assertListSize("Expected " + expected + " items named `recent-N` in 
recent items", recentItems, expected);
+    }
 }

Reply via email to