0

I have created a class that looks for email attachments for closed cases. My goal is to delete those attachments. The issue I am having is that I am unable to get to %100 code coverage. My execute method does not get any coverage. Any guidance would be greatly appreciated.

Here is my class:

global class HarveyAttachmentDeleteBatch implements Database.Batchable<sObject>, Database.Stateful {

    global Set<Id> setAttachmentIds = new Set<Id>();
    public String atts;
    private date querydate;


    global Integer recordsProcessed = 0;

    public HarveyAttachmentDeleteBatch (date startdate){

       querydate = startdate;


    } 

    global Database.QueryLocator start(Database.BatchableContext att){
        return Database.getQueryLocator(
                                        'Select id '+ 
                                        'From EmailMessage '+ 
                                        'Where HasAttachment = true AND ParentId IN (Select Id ' +
                                                                                    'From Case '+
                                                                                    'Where ClosedDate < :querydate '+
                                                                                    'AND RecordType.Name = \'Hurricane Harvey\')'
        );

    }

    global void execute(Database.BatchableContext att, List<EmailMessage> scope){
       system.debug(scope);
        // List<Attachment> attachments = new List<Attachment>();
        for (EmailMessage objEmailMessage : scope) {
            if (objEmailMessage.attachments != null && objEmailMessage.attachments.size() > 0){
                for (Attachment objAttachment:objEmailMessage.attachments){
                    setAttachmentIds.Add(objAttachment.id);

                    System.debug(setAttachmentIds);
                } 
            } 
        }

        atts = 'select Id from Attachment Where Id in :setAttachmentIds';

        List<Attachment> attlist = database.query(atts);
        if(attlist != null){
            try{
                delete attlist;
            } catch(Exception e){}
        }


    }



    global void finish(Database.BatchableContext att){



    }
}

Here is my test Class:

@isTest
private class HarveyAttachmentDeleteBatchTest {

    @testSetup
    static void setup() {
        //Date d = Date.Today().adddays(1);
        List<EmailMessage> emailmessages = new List<EmailMessage>();
        List<Case> cases = new List<Case>();
        List<Attachment> attachments = new List<Attachment>();

        Id casetype = schema.SObjectType.Case.getrecordTypeInfosByName().get('Hurricane Harvey').getRecordTypeId();

        //insert 10 cases
        for (Integer i=0;i<10;i++){
            cases.add(new Case(RecordTypeId = casetype, Status = 'Closed - Paid', Subject = 'Test '+ i));
            // cases.add(new Case(RecordTypeId = casetype, Subject = 'Test '+ i));

        }
        insert cases;
        System.debug('Cases:' + cases.size());


        //find the Cases and insert email messages for each
        for (Case casemsg : [select id from case]){
            emailmessages.add(new EmailMessage(Subject= 'Test Email Subject', HTMLBody= 'Test Email Body', 
                                               FromAddress= '[email protected]', parentId = casemsg.id));  
        }

        insert emailmessages;
        System.debug('Email Messages:' + emailmessages.size());

        // find the Emails and insert attachments for each
        for (EmailMessage emmsg : [select id from EmailMessage]){
            attachments.add(new Attachment(Name = 'Unit Test Attachment', Body= Blob.valueOf('Unit Test Attachment Body'),
                                           parentId = emmsg.id));
        }
        insert attachments;

        System.debug('Attachments:' + attachments.size());

    }

    static testmethod void test(){


        Test.startTest();

        Date d = Date.Today().adddays(1);

        Case[] ca  = [Select id, ClosedDate From Case Where IsClosed= True AND RecordType.Name = 'Hurricane Harvey' AND ClosedDate <: d];
        System.debug('ca: ' + ca);
        EmailMessage[] em = [Select id From EmailMessage Where HasAttachment = True AND parentId IN : ca];
        Attachment[] ematt = [Select id  From Attachment Where parentId IN :em];
        System.assertEquals(10, ematt.size());

        HarveyAttachmentDeleteBatch had = new HarveyAttachmentDeleteBatch(d);
        Id batchId = Database.executeBatch(had);

        delete ematt;

        Case[] ca2  = [Select id From Case Where IsClosed= True AND RecordType.Name = 'Hurricane Harvey' AND ClosedDate <: d];
        EmailMessage[] em2 = [Select id From EmailMessage Where HasAttachment = True AND parentId IN : ca2];
        Attachment[] ematt2 = [Select id  From Attachment Where parentId IN :em2];
        System.assertequals(0, ematt2.size());

        Test.stopTest();
    }

}
4
  • I would suggest looking over this trailhead. It should provide what you are looking for : trailhead.salesforce.com/en/modules/asynchronous_apex/units/… Commented Nov 16, 2017 at 19:29
  • Thank you for the recommendation. That is exactly what I have been using. I think my problem may be in my queryLocator in my Batch class. I think when i am creating test records, maybe the HasAttachment field does not get set to TRUE right away. Not sure how to resolve for that.
    – Ivo Dimov
    Commented Nov 16, 2017 at 20:34
  • What part of your code is not covered by your test class when you do a run? Commented Nov 16, 2017 at 21:15
  • 1
    The batch class won't execute until the test.stoptest() so you need to be querying for records and asserting they were deleted after Test.stoptest()
    – cropredy
    Commented Nov 17, 2017 at 2:23

1 Answer 1

1

Didn't look at the test, but the batchable would need to look more like this to work:

public class HarveyAttachmentDeleteBatch implements Database.Batchable<sObject>{

    private Date queryDate;

    public HarveyAttachmentDeleteBatch(Date queryDate){
        this.queryDate = queryDate;
    } 

    public Database.QueryLocator start(Database.BatchableContext bc){
        return Database.getQueryLocator([
                Select Id, (Select Id from Attachments)
                From EmailMessage
                Where HasAttachment = true
                AND ParentId IN
                (
                        Select Id
                        From Case
                        Where ClosedDate < :querydate
                        AND RecordType.Name = 'Hurricane Harvey'
                )
                ]);
    }

    public void execute(Database.BatchableContext bc, List<EmailMessage> scope) {
        Map<Id, Attachment> m = new Map<Id, Attachment>();
        for (EmailMessage em : scope) {
            for (Attachment a : em.Attachments){
                m.put.add(a.Id, new Attachment(Id = a.Id)); 
            } 
        }
        delete m.values();
    }

    public void finish(Database.BatchableContext att){
    }
}

Changes I've made are:

  • Querying the attachments in the query in the start method (as the code won't work without that)
  • Not having catch(Exception e){} which is almost always a bad idea in that it hides errors that you normally need to see
  • Using static (compile-time checked) SOQL to reduce the chances of query syntax errors
  • Removing unnecessary code
  • -

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .