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 Cook Nov 22 '15 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 '15 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 '15 at 1:44
  • @Eric, This is not a one time task, we are scheduling this every night 1 AM. – javanoob Nov 22 '15 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 Cook Nov 22 '15 at 1:49
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 '15 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 '15 at 1:33
  • Or a custom setting – Eric Nov 22 '15 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 '15 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 '15 at 4:25

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.