0

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

2

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.

| improve this answer | |
2

For one thing, you shouldn't be using actual record ids in test classes. You should be creating test data fresh and not relying on existing data in your org.

That being said, you could add the SeeAllData=true clause after your @isTest declaration which will force existing data in the org to remain there during test executions. That way your contactid='003c000000O4yZt' would actually reference something.

I thought the logic leading up to if(timeCheck && nameCheck) was suspect. For example:

boolean after = (checkCase.CreatedDate >= matchVFL.Call_Date_Time__c);
boolean before = (checkCase.CreatedDate <= matchVFL.End_Window__c);

I'm not seeing where in your test data creation you are ensuring that Call_Date_Time__c and End_Window__c are within the case dates since Voice_File_Loader__c appears to not have any test data created. Again, a quick fix is to set SeeAllData but the right way to do this is without hardcoding record ids in your test methods. This becomes painfully apparent when you try to deploy to production where none of the data exists that you depended on in the sandbox.

Additionally, you might checkout this post on using mock callouts in Apex.

| improve this answer | |

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.