7

Are stateful member variable of Batch Apex class maintain state after finish method when accessed in a test method. e.g.

global  class SampleBatch implements      Database.Batchable<SObject>,Database.Stateful {

    global integer count;
    global SampleBatch (){count =0;} 
    //START
    global Database.QueryLocator start(Database.BatchableContext BC) {         
        return Database.getQueryLocator(queryString);                 
    }    

    //EXECUTE 
    global void execute (Database.BatchableContext BC,List<sObject> scope){
     count++;
    }
    //FINISH
    global void finish(Database.BatchableContext BC){
    }


}

When I try to access count variable in Apex Test Class it gives me value as 0, is it expected behavior?

2 Answers 2

13

Yes, this is the expected behavior, but not for the reason you think. When you call Database.executeBatch, it serializes the class and keeps a copy of it. That means that the class instance you pass to Database.executeBatch is not the same instance that runs when the class is later executed (after Test.stopTest).

If you want to get the value back out (perhaps to verify the unit test behavior), you need to put the result in a static variable:

global  class SampleBatch implements      Database.Batchable<SObject>,Database.Stateful {

    global integer count;
    @TestVisible static Integer testCount;

    global SampleBatch (){count =0;} 
    //START
    global Database.QueryLocator start(Database.BatchableContext BC) {         
        return Database.getQueryLocator(queryString);                 
    }    

    //EXECUTE 
    global void execute (Database.BatchableContext BC,List<sObject> scope){
     count++;
    }
    //FINISH
    global void finish(Database.BatchableContext BC){
        testCount = count;
    }
}

You can then validate the result afterwards:

Test.startTest();
Database.executeBatch(new SampleBatch());
Test.stopTest();
System.assertEquals(1, SampleBatch.testCount);

If your batch class were doing something else, like modifying records, you could verify the results by using a query.

4
  • 3
    @RahulSharma As far as I know, stuff like this isn't in the docs. I just happen to spend a lot of time experimenting to discover what makes things tick.
    – sfdcfox
    Commented Feb 23, 2017 at 7:20
  • So... this is great, guys, but I am still struggling with one thing: my test class has a static variable (boolean). It is set to false; It also has a SimpleFinishAction instance (which is an instance of a finishAction interface defined in the Batch Class) with a method .onFinish() that is supposed to set the boolean to true. Batch class, in the finish block, calls onFinish on the SimpleFinishAction instance and - if I debug within Batch - I can see the static boolean is then set to true. However, when the test.StopTest() happens, the assertion fails, as the boolean is false again. What gives?
    – kanczi
    Commented Dec 5, 2023 at 13:22
  • @kanczi You should make your own question for this.
    – Derek F
    Commented Dec 5, 2023 at 15:47
  • @kanczi We'd have to see your code. The code I demonstrate here definitely works as expected, and I'd expect the Boolean to be set correctly. I'll be happy to take a look at it for you, as well as many of us here.
    – sfdcfox
    Commented Dec 5, 2023 at 16:13
1

As per the documentation related to Batch Apex

If you specify Database.Stateful in the class definition, you can maintain state across these transactions. When using Database.Stateful, only instance member variables retain their values between transactions. Static member variables don’t retain their values and are reset between transactions. Maintaining state is useful for counting or summarizing records as they’re processed. For example, suppose your job processed opportunity records. You could define a method in execute to aggregate totals of the opportunity amounts as they were processed.

So, answer to your first point:

  • Are stateful member variable of Batch Apex class maintain state after finish method when accessed in a test method

Ans: No (you need static member as mentioned in an asnwer from @sfdcfox)

P.S. I was about to answer the other point but answers have come on that from others.

You must log in to answer this question.

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