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?

  • Reading this I would assume your batch size is greater than 1. (what is not valid for tests) – Basti Dec 1 '17 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 – Oleksandr Berehovskyi Dec 1 '17 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. – Basti Dec 1 '17 at 12:31
  • 2
    @Basti yes, I just double-checked and size of toProcess is 1 – Oleksandr Berehovskyi Dec 1 '17 at 12:39
  • This question isn't really an MVR since we don't know for instance what's in AccountBuilder. – Adrian Larson Dec 1 '17 at 14:11
2

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.

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.