-3

I am a newbie in salesforce. I have a batch apex class. I wrote a test class for the class and my test method is passed but am not getting the code coverage. I have covered 42% of the code.

Apex Class:

global class EF_OKTA_Queue_Batch implements Database.Batchable <sObject>, Database.AllowsCallouts
{
private String query;
private list<EF_OKTA_Queue__c> lstoktaQueueUpdate = new list<EF_OKTA_Queue__c>();

global EF_OKTA_Queue_Batch ()
{
     query =    EF_SOQL_Statements__c.getValues('EF_OKTA_Queue_Batch_Query').Type__c + ' ' + EF_SOQL_Statements__c.getValues('EF_OKTA_Queue_Batch_Query').Fields__c +
                EF_SOQL_Statements__c.getValues('EF_OKTA_Queue_Batch_Query').Relationship_fields__c + ' from ' +  EF_SOQL_Statements__c.getValues('EF_OKTA_Queue_Batch_Query').Object__c +
                ' where ' + EF_SOQL_Statements__c.getValues('EF_OKTA_Queue_Batch_Query').Filter__c;

}


global Database.QueryLocator start(Database.BatchableContext bc)
{
    return Database.getQueryLocator(query);
}


global void execute(Database.BatchableContext BC, List <EF_OKTA_Queue__c> scope)
{
    List<String> queueWithEmptyURL       = new List<String>();
    List<EF_OKTA_Queue__c> itemsToUpdate = new List<EF_OKTA_Queue__c>();
    Map<String, String> errorsToLog      = new Map<String, String>();
    EF_OKTA_RESTAPI objEFAPI             = null;

    for (EF_OKTA_Queue__c oktaQueue: scope) {
        if (oktaQueue.OKTA_URL__c == null || oktaQueue.OKTA_URL__c.trim() == '') {
            queueWithEmptyURL.add(oktaQueue.id);
            continue;
        }
        // After 15 minutes (Scheduled Job) mark status to complete
        if (oktaQueue.EF_Requested_Resource__r.EF_Resource_Metadata__r.Type__c == 'HYBRID AUTOMATED' && oktaQueue.CreatedDate.addMinutes(15) < Datetime.now()) {
            // additional logic in trigger
            oktaQueue.Status__c = 'Complete';
        } else if (oktaQueue.EF_Requested_Resource__r.EF_Resource_Metadata__r.Type__c == 'HYBRID' && oktaQueue.CreatedDate.addMinutes(15) < Datetime.now()) {
            // additional logic in trigger
            oktaQueue.Status__c = 'Complete';
        } else if (oktaQueue.EF_Requested_Resource__r.EF_Resource_Metadata__r.Type__c == 'AUTOMATED') {
            // API Class object
            objEFAPI = new EF_OKTA_RESTAPI();
            // disable error log to avoid problems with executing a call, storing error record and getting an exception when trying to execute second call
            objEFAPI.setDisableErrorLog(true);
            // Execute call and query for current user data / profile
            String currentJSON = objEFAPI.getOKTAAttributes(oktaQueue.OKTA_URL__c);
            // extract Synchronisation Status
            String status = EF_OKTA_Queue_Batch.getSyncState(currentJSON);

            if (status == 'SYNCHRONIZED') {
                // sync status is ok so let's mark queue item as complete
                oktaQueue.Status__c = 'Complete';
            } else {
                // not synced yet, let's try some other time ...
                oktaQueue.number_tried__c += 1;

                // there might be an error so let's log it
                if ('' == status) {
                    errorsToLog.put(oktaQueue.id, currentJSON);
                }
            }
        }

        itemsToUpdate.add(oktaQueue);
    }

    try {
        // process queueWithEmptyURL first (cannot do it future)
        EF_OKTA_Queue obj = new EF_OKTA_Queue();
        obj.execute(queueWithEmptyURL);

        // update items that already have url
        if (itemsToUpdate.isEmpty() == false) {
            update itemsToUpdate;
        }
    } catch(Exception ex) {
        string strError = '';
        for (EF_OKTA_Queue__c oktaQueue: scope) {
            strError = (strError!='') ? (strError +  ',' + oktaQueue.id) : oktaQueue.id;
        }
        EF_Error_Log.logException('EF_OKTA_Queue_Batch', strError, 'DML', 'HIGH', ex.getMessage() +  '\n\nStack Trace:\n' + ex.getStackTraceString());
    }

    // if there were some invalid responses log them as errors into the log object
    if (errorsToLog.isEmpty() == false) {
        String message = '';
        for (String queueId : errorsToLog.keySet()) {
            message = errorsToLog.get(queueId);
            if (message == '') {
                message = 'JSON Response was empty ...';
            }
            EF_Error_Log.logException('EF_OKTA_Queue_Batch', queueId, 'OKTA', 'HIGH', message);
        }
    }
}

global void finish(Database.BatchableContext BC)
{
    //Final Actions: requirements not defined yet will update the code
}

global static string getSyncState(string jsonString)
{
    string status = '';
    if (jsonString == null || jsonString.trim() == '') {
        return status;
    }

    try {
        Map<String, Object> tmp = (Map<String, Object>) JSON.deserializeUntyped(jsonString);

        if (false == tmp.containsKey('syncState')) {
            return status;
        }

        status = (String) tmp.get('syncState');
    } catch (Exception e) {
        // we don't care about the error here, it just means that status is not
        // synchronised and we need to repeat the query/request
        // json response will be logged by the calling method above
    }

    return status;
}

}

Test Class:

@isTest
private class EF_OKTA_Queue_Batch_Test
{

static TestMethod void OKTAQueueBatchTest()
{   
     Database.QueryLocator QueryLoc;
     Database.BatchableContext BatchCont;
     List<EF_OKTA_Queue__c> lstOKTAQ= new List<EF_OKTA_Queue__c>();

     EF_SOQL_Statements__c objStmts= EF_DataFactory_Utility.insert_EF_SOQL_Statements();

     EF_OKTA_Queue_Batch ObjOKTAQbatch = new EF_OKTA_Queue_Batch();

     ID batchprocessid = Database.executeBatch(ObjOKTAQbatch,200);
     System.debug('######EXECUTE BATCH'+ batchprocessid);        

     List<EF_OKTA_Queue__c> lstOKTAQueue = new List<EF_OKTA_Queue__c>();

     lstOKTAQueue = EF_DataFactory_Utility.insert_EF_OKTA_Queue();        
     insert lstOKTAQueue;

     QueryLoc= ObjOKTAQbatch.start(BatchCont);

     System.debug(BatchCont);

     Database.QueryLocatorIterator QueryIterate = QueryLoc.iterator();
     while (QueryIterate.hasNext())
     {
         EF_OKTA_Queue__c objQueue = (EF_OKTA_Queue__c)QueryIterate.next();           
         System.debug(objQueue);
         System.debug(objQueue.OKTA_URL__c);
         lstOKTAQ.add(objQueue);
     }       

     ObjOKTAQbatch.execute(BatchCont, lstOKTAQ);
     ObjOKTAQbatch.finish(BatchCont); 

     String json = '{'+
        '    \"items\": ['+
        '        {'+
        '            \"id\": \"pn0\",'+
        '            \"syncState\": \"0\",'+
        '            \"managerID\": \"pc0\"'+
        '        },'+
        '        {'+
        '            \"id\": \"pn1\",'+
        '            \"syncState\": \"1\",'+
        '            \"managerID\": \"pc1\"'+
        '        },'+
        '        {'+
        '            \"id\": \"pn2\",'+
        '            \"syncState\": \"2\",'+
        '            \"managerID\": \"pc2\"'+
        '        }'+
        '    ]'+
        '}';

    EF_OKTA_Queue_Batch.getSyncState(json);      



 }
}

Please help me out.

Thanks in Advance!!!

  • Please select your code and use the {} button to format it; you get a preview below. – Keith C Mar 18 '14 at 12:04
  • am not able to do it. Please help me out. – Cool Damsel Mar 18 '14 at 12:21
  • 2
    OK I've done it. Please use that formatting when you post code in future. – Keith C Mar 18 '14 at 12:30
8

You can see which lines of your class are covered and which are not by using the Developer Console, see the salesforce help for details on how to view coverage and to see a screenshot of the coverage view. Add additional test methods to cover each branch of your conditional logic. If you aren't sure how to test a certain block of code, ask yourself what conditions cause that code to run under normal circumstances, and design a test to replicate those conditions. Also remember that these are meant to be unit tests, not integration tests; it's fine to create data in your tests that tests only a certain part of your process.

Some of your conditionals are based on record CreatedDate values. These can be hard to test because you can't set the CreatedDate directly, however, if you load test data from a static resource you can include CreatedDate in the csv file.

Sometimes you may not be able to test every line of code within a file, for example, some error conditions can be hard to replicate in a test. The requirement for deployment to production is 75% org-wide coverage; individual files can be lower than 75% if necessary as long as the org-wide coverage is ok.

  • yeah i tried from the dev console but still am able to progress only 49% – Cool Damsel Mar 18 '14 at 13:37
  • If there is a section of code you cannot figure out how to test, update your question to indicate where the issue is. – Jason Clark Mar 18 '14 at 18:08
6

There are a lot of branches in you class that are not being covered by this single test. For example "if (errorsToLog.isEmpty() == false)" - has about 7 lines that are not being covered.

You need to write further test methods with data that will run down these routes.

Follow Jason Clark's answer to access your coverage in the Developer Console so you get to a view of your class something like this:

Developer console screenshot

And this will help you work out which routes you need to test.

I would recommend replicating you test method (leaving the original in tact) and then alter your JSON and the other data dependant code to meet the different conditions (again, much like Jason Clark said! [I did vote your answer Jason!])

  • I am not sure of what need to be passed. Am a newbie in salesforce. Please Help me out. – Cool Damsel Mar 18 '14 at 12:41
  • i passed values for json method and that method is covered. but the code within my constructor is not getting covered – Cool Damsel Mar 18 '14 at 14:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.