2

1) I have a custom object "ObjectA__c" with three custom fields "Start_Date__c" and "End_Date__c" and "Status__c".

2) There is already process on this object which runs every time a record of object (ObjectA__c) is created or updated and it checks the following condition :

If Start_Date__c < TODAAY() AND End_Date__c > TODAY()

and based on the above formula evaluation sets the field "Status__c" to 'Yes' otherwise 'No'

But customer asked me to write a batch job which runs every night and looks at each and every record in ObjectA__c and updates the Status__c field based on the start and end dates..

so I developed a batch and here is the pseudo code:

public class SimpleBatch implements Database.Batchable<sObject>{

    public Database.QueryLocator start(Database.BatchableContext BC){
        String query = 'SELECT Id,Start_Date__c,End_Date__c,Status__c FROM 
            ObjectA__c WHERE IsDeleted = FALSE';
        query = query + ' AND Start_Date__c!=NULL AND End_Date__c!=NULL';
        return Database.getQueryLocator(query);
    }

    public void execute(Database.BatchableContext BC,List<ObjectA__c> scope){
        List<ObjectA__c> objsToUpdate = new List<ObjectA__c>();
        for(ObjectA__c Obj:scope){
            if((Obj.Start_Date__c <= Date.today()) 
            && (Obj.End_Date__c >=Date.today())){
                if(Obj.Status__c != 'Yes'){
                    Obj.Status__c = 'Yes';
                    objsToUpdate.add(Obj);
                }
            }else if((Obj.Start_Date__c > Date.today()) 
            || (Obj.End_Date__c < Date.today())){
                if(Obj.Status__c != 'No'){
                    Obj.Status__c = 'No';
                    objsToUpdate.add(Obj);
                }
            }
        }
        update objsToUpdate;
    }

    public void finish(Database.BatchableContext BC){
    }

}

Test class:

@isTest
public class SimeplTest {

        @isTest
        public static void scenario_one(){
            ObjectA__c obj = new ObjectA__c();
            obj.Start_Date__c = Date.today().addDays(-2);
            obj.End_Date__c = Date.today().addDays(5);
            insert obj;
            Test.startTest();
            SimpleBatch batch = new SimpleBatch();
            Database.executeBatch(batch);
            Test.stopTest();
        }

    }

When I isnert record in test class process is picking it up and changing the status so my batch does not have any thing to process and this is resulting in below 75% of coverage for my batch class.

Any suggestions on how to handle this?

8
  • Doesn't this kind of prove that this batch won't actually do anything? I had a customer ask for something very similar. It was purely because they didn't trust the code, so wanted a batch process in place 'to make sure it works'. I managed to convince them that the batch process would never actually do anything, so they reluctantly agreed to drop that 'requirement'.
    – Nick C
    Nov 22, 2015 at 1:34
  • @NickCook, lets say i have record created in last month and at that time the status is set to Yes but after one month if no one is touching the record there is no way to update the status unless batch process is cleaning the records every night..I hope this clarifies your doubt.
    – javanoob
    Nov 22, 2015 at 1:38
  • @javanoob - yes but you could do a one time data update and solve the issue....Easier that writing a batch class and maintaining that
    – Eric
    Nov 22, 2015 at 1:44
  • @Eric, This is not a one time task, we are scheduling this every night 1 AM.
    – javanoob
    Nov 22, 2015 at 1:46
  • 2
    I think he's saying that as time progresses, the Status will no longer be true. Which then raises the question, why isn't the Status a formula?
    – Nick C
    Nov 22, 2015 at 1:49

1 Answer 1

4

In your test class add a static variable:

public static boolean STOPTRIGGER = false;

In your trigger check that variable as such in the first line:

if(SimpleTest.STOPTRIGGER) return;

this will allow you to control in your tests when the trigger runs and when it does not allowing you to assert for the proper values.....

9
  • Do you recommend any other work around because the process was created by my admin using process builder and she would ask me so many questions if I ask her to add this condition.
    – javanoob
    Nov 22, 2015 at 1:31
  • Add a field to the object that the PB checks as part of the criteria and only use it during test methods.
    – Eric
    Nov 22, 2015 at 1:33
  • Or a custom setting
    – Eric
    Nov 22, 2015 at 1:43
  • 2
    It may be inconsequential to coverage, but yeah, I suppose I didn't think that through. The custom setting idea actually works wonders if leveraged properly; in one project I was on, I cut production deployment times from 55 minutes to about 25-30 minutes just by disabling triggers that were not being tested by a particular unit test. It also let us turn triggers on/off without deployments at all, which was bonus.
    – sfdcfox
    Nov 22, 2015 at 3:25
  • 2
    @javanoob A full exposition won't fit in a comment, but basically you "disable" triggers while setting up your unit test data. @TestSetup has reduced the need for this framework, but you can still benefit from it even using that new annotation. The idea is that is that you can skip all the extra queries/DML operations/logic that you're not interested in testing. Each of your triggers starts with if(!Utils.isTriggerEnabled('some-value')) return;, where utils uses custom settings/logic to skip triggers conditionally. If you want more, do feel free to ask a question.
    – sfdcfox
    Nov 22, 2015 at 4:25

You must log in to answer this question.

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