@Test(expected = ConnectionException.class)
  public void testCreateBulkWithTimeOutException() throws Exception {
    SalesforceConnector connector = new SalesforceConnector();
    SaveResult saveResult = Mockito.mock(SaveResult.class);
    PartnerConnection partnerConnection = Mockito.mock(PartnerConnection.class);
    when(partnerConnection.create(Mockito.argThat(new SObjectArrayMatcher())))
        .thenReturn(new SaveResult[] {saveResult});
    connector.setConnection(partnerConnection);
    BulkConnection bulkConnection = Mockito.mock(BulkConnection.class);
    connector.setBulkConnection(bulkConnection);
    JobInfo jobInfo = Mockito.mock(JobInfo.class);
    BatchRequest batchRequest = Mockito.mock(BatchRequest.class);
    AsyncApiException exception = Mockito.mock(AsyncApiException.class);
    doReturn(AsyncExceptionCode.InvalidSessionId).when(exception).getExceptionCode();
    doReturn(jobInfo).when(bulkConnection).createJob(any(JobInfo.class));
    doReturn(batchRequest).when(bulkConnection).createBatch(any(JobInfo.class));
    doThrow(exception).when(batchRequest).completeRequest();

    Map<String, Object> sObject = new HashMap<String, Object>();
    sObject.put(FIRST_NAME_FIELD, FIRST_NAME);
    sObject.put(LAST_NAME_FIELD, LAST_NAME);
    List<Map<String, Object>> sObjectList = new ArrayList<Map<String, Object>>();
    sObjectList.add(sObject);
    connector.createBulk(MOCK_OBJET_TYPE, sObjectList);
  }
  @Test
  public void testCreateJob() throws Exception {
    SalesforceConnector connector = new SalesforceConnector();
    BulkConnection bulkConnection = Mockito.mock(BulkConnection.class);
    connector.setBulkConnection(bulkConnection);
    ArgumentCaptor<JobInfo> expectedJobInfo = ArgumentCaptor.forClass(JobInfo.class);

    Mockito.when(bulkConnection.createJob(Mockito.isA(JobInfo.class)))
        .thenAnswer(
            new Answer<JobInfo>() {
              @Override
              public JobInfo answer(InvocationOnMock invocation) throws Throwable {
                Object[] args = invocation.getArguments();
                return (JobInfo) args[0];
              }
            });

    JobInfo actualJobInfo =
        connector.createJob(OperationEnum.upsert, "Account", "NewField", ContentType.CSV, null);
    Mockito.verify(bulkConnection).createJob(expectedJobInfo.capture());

    assertEquals(expectedJobInfo.getValue(), actualJobInfo);
    assertEquals(OperationEnum.upsert, expectedJobInfo.getValue().getOperation());
    assertEquals(actualJobInfo.getObject(), expectedJobInfo.getValue().getObject());
    assertEquals(
        actualJobInfo.getExternalIdFieldName(),
        expectedJobInfo.getValue().getExternalIdFieldName());
    assertEquals(actualJobInfo.getContentType(), expectedJobInfo.getValue().getContentType());
  }
  @Test
  public void testIsNotConnectedWhenLoginResultIsNull() throws Exception {
    SalesforceConnector connector = new SalesforceConnector();
    PartnerConnection partnerConnection = Mockito.mock(PartnerConnection.class);
    connector.setConnection(partnerConnection);
    BulkConnection bulkConnection = Mockito.mock(BulkConnection.class);
    connector.setBulkConnection(bulkConnection);

    assertFalse(connector.isConnected());
  }
  @Test
  public void testQuery() throws Exception {
    SalesforceConnector connector = new SalesforceConnector();
    final SObject sObject1 = Mockito.mock(SObject.class);
    final SObject sObject2 = Mockito.mock(SObject.class);
    final SObject sObject3 = Mockito.mock(SObject.class);
    when(sObject1.getId()).thenReturn("1");
    when(sObject2.getId()).thenReturn("2");
    when(sObject3.getId()).thenReturn("3");
    QueryResult queryResult = Mockito.mock(QueryResult.class);
    when(queryResult.getRecords())
        .thenAnswer(
            new Answer<Object>() {
              int counter = 0;

              @Override
              public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
                SObject[] result = null;
                switch (counter) {
                  case 0:
                    result = new SObject[] {sObject1};
                    break;
                  case 1:
                    result = new SObject[] {sObject2, sObject3};
                    break;
                  case 2:
                    result = new SObject[] {};
                    break;
                }
                counter++;
                return result;
              }
            });
    when(queryResult.isDone()).thenReturn(false).thenReturn(true);
    when(queryResult.getQueryLocator()).thenReturn("001").thenReturn(null);

    PartnerConnection partnerConnection = Mockito.mock(PartnerConnection.class);
    BulkConnection bulkConnection = Mockito.mock(BulkConnection.class);
    connector.setBulkConnection(bulkConnection);
    connector.setConnection(partnerConnection);

    when(partnerConnection.query(eq(MOCK_QUERY))).thenReturn(queryResult);
    when(partnerConnection.queryMore("001")).thenReturn(queryResult);

    PagingDelegate<Map<String, Object>> delegate =
        connector.query(MOCK_QUERY, new PagingConfiguration(1));
    List<Map<String, Object>> result = delegate.getPage();
    assertEquals(1, result.size());

    result = delegate.getPage();
    assertEquals(2, result.size());

    assertNull(delegate.getPage());
  }
  @Test
  public void testGetUserInfo() throws Exception {
    SalesforceConnector connector = new SalesforceConnector();
    PartnerConnection partnerConnection = Mockito.mock(PartnerConnection.class);
    connector.setConnection(partnerConnection);
    BulkConnection bulkConnection = Mockito.mock(BulkConnection.class);
    connector.setBulkConnection(bulkConnection);
    GetUserInfoResult getUserInfoResult = Mockito.mock(GetUserInfoResult.class);
    when(partnerConnection.getUserInfo()).thenReturn(getUserInfoResult);

    assertEquals(getUserInfoResult, connector.getUserInfo());
  }
  @Test
  public void testGetSessionId() throws Exception {
    SalesforceConnector connector = new SalesforceConnector();
    PartnerConnection partnerConnection = Mockito.mock(PartnerConnection.class);
    LoginResult loginResult = Mockito.mock(LoginResult.class);
    connector.setConnection(partnerConnection);
    connector.setLoginResult(loginResult);
    BulkConnection bulkConnection = Mockito.mock(BulkConnection.class);
    connector.setBulkConnection(bulkConnection);
    when(loginResult.getSessionId()).thenReturn(MOCKED_ID);

    assertEquals(connector.getSessionId(), MOCKED_ID);
  }
  @Test
  public void testDescribeSObject() throws Exception {
    SalesforceConnector connector = new SalesforceConnector();
    DescribeSObjectResult describeSObjectResult = Mockito.mock(DescribeSObjectResult.class);
    PartnerConnection partnerConnection = Mockito.mock(PartnerConnection.class);
    connector.setConnection(partnerConnection);
    BulkConnection bulkConnection = Mockito.mock(BulkConnection.class);
    connector.setBulkConnection(bulkConnection);

    when(partnerConnection.describeSObject(eq(MOCK_OBJET_TYPE))).thenReturn(describeSObjectResult);

    connector.describeSObject(MOCK_OBJET_TYPE);
  }
  @Test
  public void testAbortJob() throws Exception {
    SalesforceConnector connector = new SalesforceConnector();
    BulkConnection bulkConnection = Mockito.mock(BulkConnection.class);
    connector.setBulkConnection(bulkConnection);
    JobInfo expectedJobInfo = new JobInfo();
    String jobId = "uVsd234k23neasd";

    Mockito.when(bulkConnection.abortJob(jobId)).thenReturn(expectedJobInfo);
    JobInfo actualJobInfo = connector.abortJob(jobId);

    assertEquals(expectedJobInfo, actualJobInfo);
  }
  @Test
  public void testQuerySingle() throws Exception {
    SalesforceConnector connector = new SalesforceConnector();
    QueryResult queryResult = Mockito.mock(QueryResult.class);
    when(queryResult.getRecords()).thenReturn(new SObject[] {});
    PartnerConnection partnerConnection = Mockito.mock(PartnerConnection.class);
    BulkConnection bulkConnection = Mockito.mock(BulkConnection.class);
    connector.setBulkConnection(bulkConnection);
    connector.setConnection(partnerConnection);

    when(partnerConnection.query(eq(MOCK_QUERY))).thenReturn(queryResult);

    connector.querySingle(MOCK_QUERY);
  }
  @Test(expected = ConnectionException.class)
  public void testCreateBatchWithConnectionException() throws Exception {
    SalesforceConnector connector = new SalesforceConnector();
    BulkConnection bulkConnection = Mockito.mock(BulkConnection.class);
    AsyncApiException exception = Mockito.mock(AsyncApiException.class);
    connector.setBulkConnection(bulkConnection);

    JobInfo jobInfo = new JobInfo();
    List<Map<String, Object>> objects = new ArrayList<Map<String, Object>>();

    Mockito.when(exception.getExceptionCode()).thenReturn(AsyncExceptionCode.InvalidSessionId);
    Mockito.when(bulkConnection.createBatch(jobInfo)).thenThrow(exception);
    connector.createBatch(jobInfo, objects);
  }
  private BatchInfo setupBulkConnection(SalesforceConnector salesforceConnector)
      throws AsyncApiException {
    PartnerConnection partnerConnection = Mockito.mock(PartnerConnection.class);
    salesforceConnector.setConnection(partnerConnection);
    BulkConnection bulkConnection = Mockito.mock(BulkConnection.class);
    salesforceConnector.setBulkConnection(bulkConnection);
    JobInfo jobInfo = Mockito.mock(JobInfo.class);
    BatchRequest batchRequest = Mockito.mock(BatchRequest.class);
    BatchInfo batchInfo = Mockito.mock(BatchInfo.class);
    doReturn(jobInfo).when(bulkConnection).createJob(any(JobInfo.class));
    doReturn(batchRequest).when(bulkConnection).createBatch(any(JobInfo.class));
    doReturn(batchInfo).when(batchRequest).completeRequest();

    return batchInfo;
  }
  @Test
  public void testDescribeGlobal() throws Exception {
    SalesforceConnector connector = new SalesforceConnector();
    DescribeGlobalResult describeGlobalResult = Mockito.mock(DescribeGlobalResult.class);
    PartnerConnection partnerConnection = Mockito.mock(PartnerConnection.class);
    BulkConnection bulkConnection = Mockito.mock(BulkConnection.class);
    connector.setBulkConnection(bulkConnection);
    connector.setConnection(partnerConnection);

    when(partnerConnection.describeGlobal()).thenReturn(describeGlobalResult);

    connector.describeGlobal();

    verify(partnerConnection).describeGlobal();
  }
  @Test
  public void testGetDeletedRange() throws Exception {
    SalesforceConnector connector = spy(new SalesforceConnector());
    PartnerConnection partnerConnection = Mockito.mock(PartnerConnection.class);
    connector.setConnection(partnerConnection);
    BulkConnection bulkConnection = Mockito.mock(BulkConnection.class);
    connector.setBulkConnection(bulkConnection);
    GetServerTimestampResult getServerTimestampResult =
        Mockito.mock(GetServerTimestampResult.class);
    when(partnerConnection.getServerTimestamp()).thenReturn(getServerTimestampResult);

    connector.getDeletedRange("Account", Calendar.getInstance(), Calendar.getInstance());

    verify(partnerConnection, atLeastOnce())
        .getDeleted(eq("Account"), any(Calendar.class), any(Calendar.class));
  }
  @Test
  public void testDelete() throws Exception {
    SalesforceConnector connector = new SalesforceConnector();
    DeleteResult deleteResult = Mockito.mock(DeleteResult.class);
    PartnerConnection partnerConnection = Mockito.mock(PartnerConnection.class);
    connector.setConnection(partnerConnection);
    BulkConnection bulkConnection = Mockito.mock(BulkConnection.class);
    connector.setBulkConnection(bulkConnection);

    when(partnerConnection.delete(argThat(new StringArrayMatcher())))
        .thenReturn(new DeleteResult[] {deleteResult});

    List<String> ids = new ArrayList<String>();
    ids.add(MOCKED_ID);

    connector.delete(ids);
  }
  @Test
  public void testEmptyRecycleBin() throws Exception {
    SalesforceConnector connector = new SalesforceConnector();
    EmptyRecycleBinResult emptyRecycleBinResult = Mockito.mock(EmptyRecycleBinResult.class);
    PartnerConnection partnerConnection = Mockito.mock(PartnerConnection.class);
    connector.setConnection(partnerConnection);
    BulkConnection bulkConnection = Mockito.mock(BulkConnection.class);
    connector.setBulkConnection(bulkConnection);

    when(partnerConnection.emptyRecycleBin(argThat(new StringArrayMatcher())))
        .thenReturn(new EmptyRecycleBinResult[] {emptyRecycleBinResult});

    List<String> ids = new ArrayList<String>();
    ids.add(MOCKED_ID);

    connector.emptyRecycleBin(ids);
  }
  @Test
  public void testCreateBatch() throws Exception {
    SalesforceConnector connector = new SalesforceConnector();
    BulkConnection bulkConnection = Mockito.mock(BulkConnection.class);
    BatchRequest batchRequest = Mockito.mock(BatchRequest.class);
    connector.setBulkConnection(bulkConnection);

    JobInfo jobInfo = new JobInfo();
    List<Map<String, Object>> objects = new ArrayList<Map<String, Object>>();

    BatchInfo expectedBatchInfo = new BatchInfo();
    Mockito.when(bulkConnection.createBatch(jobInfo)).thenReturn(batchRequest);
    Mockito.when(batchRequest.completeRequest()).thenReturn(expectedBatchInfo);
    BatchInfo actualBatchInfo = connector.createBatch(jobInfo, objects);

    assertEquals(expectedBatchInfo, actualBatchInfo);
    Mockito.verify(batchRequest).addSObjects(connector.toAsyncSObjectList(objects));
  }
  @Test
  public void testCreateSingleWithNoSaveResults() throws Exception {
    SalesforceConnector connector = new SalesforceConnector();
    PartnerConnection partnerConnection = Mockito.mock(PartnerConnection.class);
    when(partnerConnection.create(Mockito.argThat(new SObjectArrayMatcher())))
        .thenReturn(new SaveResult[] {});
    connector.setConnection(partnerConnection);
    BulkConnection bulkConnection = Mockito.mock(BulkConnection.class);
    connector.setBulkConnection(bulkConnection);

    Map<String, Object> sObject = new HashMap<String, Object>();
    sObject.put(FIRST_NAME_FIELD, FIRST_NAME);
    sObject.put(LAST_NAME_FIELD, LAST_NAME);

    SaveResult returnedSaveResult = connector.createSingle(MOCK_OBJET_TYPE, sObject);

    assertNull(returnedSaveResult);
  }
  @Test(expected = ConnectionException.class)
  public void testCreateBatchForQueryWithConnectionException() throws Exception {
    SalesforceConnector connector = new SalesforceConnector();
    BulkConnection bulkConnection = Mockito.mock(BulkConnection.class);
    ArgumentCaptor<JobInfo> expectedJobInfo = ArgumentCaptor.forClass(JobInfo.class);
    AsyncApiException exception = Mockito.mock(AsyncApiException.class);
    connector.setBulkConnection(bulkConnection);

    JobInfo actualJobInfo = new JobInfo();
    String query = "SELECT Id FROM Contact";

    Mockito.when(exception.getExceptionCode()).thenReturn(AsyncExceptionCode.InvalidSessionId);
    Mockito.when(
            bulkConnection.createBatchFromStream(
                expectedJobInfo.capture(), Mockito.isA(InputStream.class)))
        .thenThrow(exception);
    connector.createBatchForQuery(actualJobInfo, query);
    assertEquals(expectedJobInfo.getValue(), actualJobInfo);
  }
  @Test
  public void testRetrieve() throws Exception {
    SalesforceConnector connector = new SalesforceConnector();
    PartnerConnection partnerConnection = Mockito.mock(PartnerConnection.class);
    BulkConnection bulkConnection = Mockito.mock(BulkConnection.class);
    connector.setBulkConnection(bulkConnection);
    connector.setConnection(partnerConnection);

    SObject sObject1 = Mockito.mock(SObject.class);
    SObject sObject2 = Mockito.mock(SObject.class);

    when(partnerConnection.retrieve(eq("Id,Name"), eq("Account"), eq(new String[] {"id1", "id2"})))
        .thenReturn(new SObject[] {sObject1, sObject2});

    List<Map<String, Object>> result =
        connector.retrieve("Account", Arrays.asList("id1", "id2"), Arrays.asList("Id", "Name"));

    assertEquals(2, result.size());
  }
  @Test
  public void testCreateBatchStream() throws Exception {
    SalesforceConnector connector = new SalesforceConnector();
    BulkConnection bulkConnection = Mockito.mock(BulkConnection.class);
    ArgumentCaptor<JobInfo> expectedJobInfo = ArgumentCaptor.forClass(JobInfo.class);
    connector.setBulkConnection(bulkConnection);

    JobInfo actualJobInfo = new JobInfo();
    InputStream stream = Mockito.mock(InputStream.class);

    BatchInfo expectedBatchInfo = new BatchInfo();
    Mockito.when(
            bulkConnection.createBatchFromStream(
                expectedJobInfo.capture(), Mockito.isA(InputStream.class)))
        .thenReturn(expectedBatchInfo);
    BatchInfo actualBatchInfo = connector.createBatchStream(actualJobInfo, stream);

    assertEquals(expectedBatchInfo, actualBatchInfo);
    assertEquals(expectedJobInfo.getValue(), actualJobInfo);
  }
  @Test
  public void testPublishTopic() throws Exception {
    SalesforceConnector connector = new SalesforceConnector();
    PartnerConnection partnerConnection = Mockito.mock(PartnerConnection.class);
    connector.setConnection(partnerConnection);
    BulkConnection bulkConnection = Mockito.mock(BulkConnection.class);
    connector.setBulkConnection(bulkConnection);
    SaveResult saveResult = Mockito.mock(SaveResult.class);
    when(saveResult.isSuccess()).thenReturn(true);
    when(partnerConnection.create(Mockito.argThat(new SObjectArrayMatcher())))
        .thenReturn(new SaveResult[] {saveResult});
    QueryResult queryResult = Mockito.mock(QueryResult.class);
    when(partnerConnection.query(eq("SELECT Id FROM PushTopic WHERE Name = 'TopicName'")))
        .thenReturn(queryResult);
    when(queryResult.getSize()).thenReturn(0);

    connector.publishTopic("TopicName", "SELECT * FROM Account", "Description");

    verify(partnerConnection, atLeastOnce()).create(Mockito.argThat(new SObjectArrayMatcher()));
  }
  @Test
  public void testUpdate() throws Exception {
    SalesforceConnector connector = new SalesforceConnector();
    SaveResult saveResult = Mockito.mock(SaveResult.class);
    PartnerConnection partnerConnection = Mockito.mock(PartnerConnection.class);
    when(partnerConnection.update(Mockito.argThat(new SObjectArrayMatcher())))
        .thenReturn(new SaveResult[] {saveResult});
    BulkConnection bulkConnection = Mockito.mock(BulkConnection.class);
    connector.setBulkConnection(bulkConnection);
    connector.setConnection(partnerConnection);

    Map<String, Object> sObject = new HashMap<String, Object>();
    sObject.put(FIRST_NAME_FIELD, FIRST_NAME);
    sObject.put(LAST_NAME_FIELD, LAST_NAME);
    List<Map<String, Object>> sObjectList = new ArrayList<Map<String, Object>>();
    sObjectList.add(sObject);

    List<SaveResult> saveResults = connector.update(MOCK_OBJET_TYPE, sObjectList);

    assertEquals(saveResults.get(0), saveResult);
  }
  @Test
  public void testConvertLead() throws Exception {
    SalesforceConnector connector = new SalesforceConnector();
    PartnerConnection partnerConnection = Mockito.mock(PartnerConnection.class);
    BulkConnection bulkConnection = Mockito.mock(BulkConnection.class);
    connector.setBulkConnection(bulkConnection);
    connector.setConnection(partnerConnection);
    LeadConvertResult result = Mockito.mock(LeadConvertResult.class);

    when(partnerConnection.convertLead(
            argThat(
                new Matcher<LeadConvert[]>() {
                  @Override
                  public boolean matches(Object o) {
                    if (!o.getClass().isArray()) {
                      return false;
                    }

                    Object[] oArray = (Object[]) o;
                    if (oArray.length != 1) {
                      return false;
                    }

                    if (!(oArray[0] instanceof LeadConvert)) {
                      return false;
                    }

                    LeadConvert leadConvert = (LeadConvert) oArray[0];

                    if (!leadConvert.getAccountId().equals(ACCOUNT_ID)) {
                      return false;
                    }

                    if (!leadConvert.getContactId().equals(CONTACT_ID)) {
                      return false;
                    }

                    if (!leadConvert.getLeadId().equals(LEAD_ID)) {
                      return false;
                    }

                    if (!leadConvert.getOpportunityName().equals(OPPORTUNITY_NAME)) {
                      return false;
                    }

                    if (!leadConvert.getOverwriteLeadSource()) {
                      return false;
                    }

                    if (!leadConvert.getDoNotCreateOpportunity()) {
                      return false;
                    }

                    if (!leadConvert.getSendNotificationEmail()) {
                      return false;
                    }

                    return true;
                  }

                  @Override
                  public void _dont_implement_Matcher___instead_extend_BaseMatcher_() {}

                  @Override
                  public void describeTo(Description description) {}
                })))
        .thenReturn(new LeadConvertResult[] {result});

    connector.convertLead(
        LEAD_ID, CONTACT_ID, ACCOUNT_ID, true, true, OPPORTUNITY_NAME, CONVERTED_STATUS, true);
  }