Skip to main content
added 160 characters in body
Source Link
Raul
  • 18.9k
  • 5
  • 42
  • 70

As endEnd to end test could not be possible with testing trigger and batch separatelyclass when it's methods are broken for unit test, another workaund could beworkaround is to call the execute's code as future; such that batch runs a future for unit tests.

A private @TestVisible variable could be used instead of Test.isRunningTest(), just a matter of choice.

As end to end test could not be possible with testing trigger and batch separately, another workaund could be is to call the execute's code as future.

End to end test could not be possible with batch class when it's methods are broken for unit test, another workaround is to call the execute's code as future; such that batch runs a future for unit tests.

A private @TestVisible variable could be used instead of Test.isRunningTest(), just a matter of choice.

Post Undeleted by Raul
Post Deleted by Raul
Source Link
Raul
  • 18.9k
  • 5
  • 42
  • 70

As end to end test could not be possible with testing trigger and batch separately, another workaund could be is to call the execute's code as future.

Still not perfect but for the current scenario atleast I am able to do an end to end test, following is an example-

Test class:

@IsTest
public class TestAccountTrigger {
    
    @IsTest 
    private static void testBatchFunctionality() {
    
        // create test data

        Test.startTest();

        // set mock

        // update records

        Test.stopTest();

        // verify records as processed by batch
    }
}

Trigger:

trigger AccountTrigger on Account (after update) {
    if(myCondition) {
        if(Test.isRunningTest()) {
            // call batch's method as future as Database.executeBatch is counted as DML
            MyBatchClass.executeCalloutAsFuture(Trigger.newMap.keySet());
        } else {
            Database.executeBatch(new MyBatchClass(), 1);
        }
    }
}

Batch apex:

public class MyBatchClass implements Database.Batchable<SObject>, 
    Database.AllowsCallouts {
    
    public Set<Id> accountSet = new Set<Id>();

    public OrderPABXBatch(Set<Id> accountSet) {
        this.accountSet = accountSet;
    }

    // start method
    public Database.QueryLocator start(Database.BatchableContext BC){ 
        return getQueryLocator(this.accountSet);
    }

    private Database.QueryLocator getQueryLocator(Set<Id> accountSet) {
        return Database.getQueryLocator([SELECT Id FROM Account WHERE Id IN :accountSet]);
    }

    // call execute method from test context
    @future(callout=true)
    public static void executeCalloutAsFuture(Set<Id> orderSet) {

        MyBatchClass batchInstance = new MyBatchClass(orderSet);
        // Get an iterator
        Database.QueryLocatorIterator iterator =  batchInstance.getQueryLocator().iterator();
        
        List<Account> accounts = new List<Account>();
        // Collect the first record
        if(iterator.hasNext()) {
            accounts.add((Account) iterator.next());
        }
        if(!accounts.isEmpty()) {
            batchInstance.execute(null, accounts);
        }
    }


    // only relevant execute method
    public void execute(Database.BatchableContext batchableContext, 
        List<Account> accounts) {

        for(Account account: accounts) {

            // make http request callout

            // based on response update account
        }
    }
}