Salesforce Stack Exchange is a question and answer site for Salesforce administrators, implementation experts, developers and anybody in-between. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Given the following batch code:

global without sharing class POCBatch implements Database.Stateful, Database.Batchable<Sobject>{

        public static List<String> staticList = new List<String>();
        public List<String> nonStaticList = new List<String>();

        global Database.QueryLocator start(Database.BatchableContext BC) {
            return Database.getQueryLocator([Select Id from Account limit 1]);
        }

        global void execute(Database.BatchableContext BC, List<Sobject> scope) {

            staticList.add('StaticAdd');
            nonStaticList.add('NonStaticAdd');
        }

        global void finish(Database.BatchableContext BC) {
            System.debug('finishStaticList: '+staticList);
            System.debug('finishNonStaticList: '+nonStaticList);
        }
}

and the following test method:

@isTest
private class POCBatchTest {
    @isTest
    static void testPOCBatch(){
        insert new Account(Name = 'For Test');
        POCBatch poc = new POCBatch();
        Test.startTest();
        Database.executeBatch(poc);
        Test.stopTest();
        System.debug('test method static list: '+POCBatch.staticList);
        System.debug('test method non-static list: '+poc.nonStaticList);

    }
}

If you run in a batch versus text context, it gives different results. In both case it is selecting a single Account from the org (but doesn't do anything with it).

Batch context debug output:

finishStaticList: ()

finishNonStaticList: (NonStaticAdd)

Test method debug output:

finishStaticList: (StaticAdd)

finishNonStaticList: (NonStaticAdd)

test method static list: (StaticAdd)

test method non-static list: ()

My questions are:

1) Why are there differences in the finish method output in the different contexts?

2) It appears that the static context is lost in the batch, but the non-static context is lost in the test method. So how can I test the list's contents in the batch's test method?

share|improve this question

Static variables are wiped out between transactions; since a unit test is a single transaction, the static variable persists during a unit test, but not when ran as live code. The local variable is a bit trickier. You see, when you use Database.executeBatch, it actually serializes the class, which means a copy is created and run later. The version you have "in memory" in the unit test isn't the same object that gets run. This is similar to the reason you need to query records from a database after you perform a DML operation to verify the new values.

For testing purposes, consider doing this:

global without sharing class POCBatch implements Database.Stateful, Database.Batchable<Sobject>{
        public List<String> nonStaticList = new List<String>();
        @TestVisible static POCBatch self;

        global Database.QueryLocator start(Database.BatchableContext BC) {
            self = this;
            return Database.getQueryLocator([Select Id from Account limit 1]);
        }

        global void execute(Database.BatchableContext BC, List<Sobject> scope) {
            nonStaticList.add('NonStaticAdd');
        }

        global void finish(Database.BatchableContext BC) {
            System.debug('finishNonStaticList: '+nonStaticList);
        }
}

From there, you can modify your unit test:

@isTest
private class POCBatchTest {
    @isTest
    static void testPOCBatch(){
        insert new Account(Name = 'For Test');
        POCBatch poc = new POCBatch();
        Test.startTest();
        Database.executeBatch(poc);
        Test.stopTest();
        System.debug('test method non-static list: '+POCBatch.self.nonStaticList);

    }
}
share|improve this answer
    
That certainly makes sense. But when I tried your code POCBatch.self.nonStaticList still returned empty. – George S. yesterday
1  
@GeorgeS. This used to work. I'm pretty sure, anyways. I'm going to check some old source code. – sfdcfox yesterday

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.