3

Nothing special. I am testing batch class and I am facing the following exception:

Error Message

System.UnexpectedException: Error processing messages

Stack Trace

Class.System.Test.stopTest: line 19, column 1

Class.DatabaseAsyncTest.testdoDMLBatchIsSucessful: line 10, column 1

Class under test

public abstract with sharing class DatabaseAsync implements Database.Batchable<SObject>, Database.Stateful{
    public Integer batchSize {get; set;}
    protected Boolean allOrNone {get; set;}
    protected List<SObject> toProcess = new List<SObject>();

    protected DatabaseAsync(List<Id> toProcess){
        this(toProcess, true);
    }

    protected DatabaseAsync(List<Id> toProcess, Boolean allOrNone){
        populateFieldsForDML(toProcess, allOrNone);
    }

    protected DatabaseAsync(List<SObject> toProcess){
        this(toProcess, true);
    }

    protected DatabaseAsync(List<SObject> toProcess, Boolean allOrNone){
        populateFieldsForDML(toProcess, allOrNone);
    }

    protected abstract void doDML();

    private void populateFieldsForDML(List<Id> toProcess, Boolean allOrNone){
        List<SObject> toProcessSObjs= new List<SObject>();
        for(Id recId :toProcess){
            SObject sobjToDelete = recId.getSobjectType().newSObject(recId);
            toProcessSObjs.add(sobjToDelete);
        }
        populateFieldsForDML(toProcessSObjs, allOrNone);
    }

    private void populateFieldsForDML(List<SObject> toProcess, Boolean allOrNone){
        this.toProcess.addAll(toProcess);
        this.toProcess.sort();
        this.allOrNone = allOrNone;
        this.batchSize = 200;
    }

    public Iterable<sObject> start(Database.BatchableContext bc) {
        return toProcess;
    }

    public void execute(Database.BatchableContext BC, List<sObject> scope){
        doDML();
    }

    public void finish(Database.BatchableContext BC){
    }

    public static void doDML(DatabaseAsync action){
        Database.executeBatch(action, action.batchSize);
    }
}

Test class

@isTest
private class DatabaseAsyncTest {
    @isTest
    static void testdoDMLBatchIsSucessful(){
        SetupData testData = new SetupData();
        System.runAs(testData.testUser){
            testData.initClassUnderTest();
            Test.startTest();
                DatabaseAsync.doDML(testData.classUnderTest);
            Test.stopTest(); //this is line 10
            List<Account> accts = [
                select Id
                from Account
                ];
            System.assertEquals(1, accts.size(), 'Incorrect number of created records as a result of batche execution');
        }
    }

    public class SetupData{
        public User testUser {get; set;}
        public ClassUnderTest classUnderTest {get; set;}

        public SetupData(){
            testUser = TestUserData.getUserForTest()
                .setProfile(ProfileUtilities.ProfileType.Manager)
                .save()
                .getRecord();
        }

        public void initClassUnderTest(){
            classUnderTest = new ClassUnderTest(new List<Id>{UserInfo.getUserId()});
        }
    }

    public class ClassUnderTest extends DatabaseAsync{
        public ClassUnderTest(List<Id> sobjs){
            super(sobjs);
        }

        public override void doDML(){
            AccountBuilder.getBuilder()
                .setName('Just Name')
                .save();
        }
    }
}

AccountBuilder class

public class AccountBuilder {
    @testVisible
    private class Builder{
        @testVisible
        private Account record;

        private Builder(){
            this.record = new Account();
            this.record.Name = Random.generateRandomString(10);
        }

        public Builder setName(){
            this.record.Name = Random.generateRandomString(10);
            return this;
        }

        public Account getRecord(){
            return this.record;
        }

        public Builder save(){
            upsert this.record;
            return this;
        }
    }

    public static Builder getBuilder(){
        return new Builder();
    }
}

Can I figure out somehow what is a problem? Or it is just one more SF platform bug?

6
  • Reading this I would assume your batch size is greater than 1. (what is not valid for tests)
    – itsmebasti
    Commented Dec 1, 2017 at 12:20
  • @Basti I tried setting 1 size of batcj size before Test.startTest(); line testData.classUnderTest.batchSize = 1;but I had the same exception Commented Dec 1, 2017 at 12:27
  • But are you sure there is only one Element in your scope? cause if there are more it might fail too. Setting it to 1 for two elements would require an (illegal) second batch run.
    – itsmebasti
    Commented Dec 1, 2017 at 12:31
  • 2
    @Basti yes, I just double-checked and size of toProcess is 1 Commented Dec 1, 2017 at 12:39
  • This question isn't really an MVR since we don't know for instance what's in AccountBuilder.
    – Adrian Larson
    Commented Dec 1, 2017 at 14:11

1 Answer 1

4

I ran into the same issue seems to be related to having a subclass DatabaseAsyncTest.ClassUnderTest that implements Database.Batchable (DatabaseAsync).

If you create DatabaseAsyncTest.ClassUnderTest in it's own class (e.g. DatabaseAsyncMock), everything should be fine.

1

You must log in to answer this question.

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