[SalesForce] Test Class for Batch Apex with Webservice Callout

I have this batch class that's been nothing but trouble from the start. After several hurdles I finally got it working. My problem now is I have NO IDEA how to test it. After some brute force I can get around 25% covered, but I don't understand how to proceed. Here's my batch code:

global class batchAccountUpdate implements Database.Batchable<sObject>, Database.AllowsCallouts{

    public string obj;
    public string query;

    global Database.QueryLocator start(Database.BatchableContext BC)
    {
        obj = 'ACA';
        query = 'Select Id, CreatedDate, CreatedBy.Name, Attest_ID__c from Case where Ticket_Type__c = :obj';
        return Database.getQueryLocator(query);
    }

    global void execute(Database.BatchableContext BC, List<case> scope)
    {
        List<Voice_File_Loader__C> searchVFL =  [Select Id, Call_Date_Time__c, End_Window__c, Agent_Name__c, Voice_File_Location__c from Voice_File_Loader__c];
        List<Voice_File_Loader__c> VFL = new list<Voice_File_Loader__c>();
        List<Attachment> attlist = new List<attachment>();

        for (case checkCase : scope){
            for (Voice_File_Loader__c matchVFL :searchVFL){
                boolean after = (checkCase.CreatedDate >= matchVFL.Call_Date_Time__c);
                boolean before = (checkCase.CreatedDate <= matchVFL.End_Window__c);
                boolean timeCheck = (after && before);
                boolean nameCheck = (checkCase.CreatedBy.Name.equalsIgnoreCase(matchVFL.Agent_Name__c));
                if (timeCheck && nameCheck){
                    Attachment att = new Attachment();
                    Http binding = new Http();
                    HttpRequest req = new HttpRequest(); 
                    req.setMethod('GET');                                                                                  
                    req.setEndpoint(matchVFL.Voice_File_Location__c);

                    HttpResponse res = new HttpResponse();
                    if (Test.isRunningTest()){
                        blob b = Blob.valueof('Complete');
                        SingleRequestMock fakeResponse = new SingleRequestMock(200, 'Complete', b, null);
                    }else{
                        res = binding.send(req);
                    }

                    boolean redirect = false;
                    if(res.getStatusCode() >=300 && res.getStatusCode() <= 307 && res.getStatusCode() != 306) {
                        do {
                            redirect = false; 
                            String loc = res.getHeader('Location'); 
                            if(loc == null) {
                                redirect = false;
                                continue;
                            }
                            req = new HttpRequest();
                            req.setEndpoint(loc);
                            req.setMethod('GET');
                            res = binding.send(req);
                            if(res.getStatusCode() != 500) { // 500 = fail
                                if(res.getStatusCode() >=300 && res.getStatusCode() <= 307 && res.getStatusCode() != 306) {
                                    redirect= true;
                                }
                            }
                        } while (redirect && Limits.getCallouts() != Limits.getLimitCallouts());
                    }

                    Blob b = res.getbodyasblob();
                    if(b.size() > 0){
                        att.name = 'Voice Attestation.wav'; 
                        att.body = b;
                    } else if (b.size() == 0){              
                        att.name = 'File Not Found'; 
                        String myString = 'File Not Found';
                        Blob c = Blob.valueof(myString);
                        att.body = c;
                    }

                    att.parentid = checkCase.Id;
                    attlist.add(att);
                    VFL.add(matchVFL);
                }
            }   
        }

        insert attlist;
    }   

    global void finish(Database.BatchableContext BC)
    {
    }
}   

And here is my brute forced test class:

@isTest public class extracttest {
    public static testmethod void testAccountCallout() {
        test.startTest();
        Case testcase = new Case(contactid='003c000000O4yZt',status='new',ticket_type__c='ACA',ticket_sub__c='application',priority='medium',description='blah');
        list<case> scope = new list<case>();
        scope.add(testcase);
        insert scope;
        batchAccountUpdate batch = new batchAccountUpdate();    batch.searchvfL = searchVFL;
        batch.start(null);
        batch.execute(null, scope);
        batch.finish(null);
        database.executebatch(batch,1);
        test.stopTest();     
    }
}

Can someone explain to me how to advance my code coverage? Any help is appreciated. I've looked through the documents and tried to find some examples but they are few and far in between. Thanks in advance. -ross

Best Answer

Adding to Adam's answer, you need to create all the test data you need - Contacts, Cases and Voice_File_Loader__c records. I suspect the reason you are hitting 25% is that you code reaches this point:

for (Voice_File_Loader__c matchVFL :searchVFL){

And there are no records to loop over (unless there is a trigger doing that or something?

Once you have all the data in place, you can just run the test like this:

@isTest public class extracttest {
    public static testmethod void testAccountCallout() {
Contact con - new Contact(lastName = 'Tester');
insert con;        
Case testcase = new Case(contactid= con.Id,status='new',ticket_type__c='ACA',ticket_sub__c='application',priority='medium',description='blah');

       batchAccountUpdate batch = new batchAccountUpdate();

        test.starttest();
        database.executebatch(batch,1);
        test.stopTest();     
    }
}

The stoptest will force the batch to run as if it were being called normally, you can then perform any asserts to check the data is correct.

Related Topic