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.

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
            }
        }
    }

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