I have a batch apex class that does what I want it to do but I am currently trying to test it and because I am using some objects from financial force, creating testdata has been a bit complicated. Spoke to support and they recommended using data from the organization itself. I have done this and it works in the sandbox but on deployment I get an error stating System.UnexpectedException: No more than one executeBatch can be called from within a test method. Please make sure the iterable returned from your start method matches the batch size, resulting in one executeBatch invocation. Stack Trace: External entry point
This is my test class
@isTest(SeeAllData=true)
public class ServicesBatchTest {
@IsTest
static void testExecute() {
// Fetch a small set of existing invoices to use in the test
List<c2g__codaInvoice__c> testInvoices = [SELECT Id, c2g__Account__c, c2g__InvoiceStatus__c, LastModifiedDate
FROM c2g__codaInvoice__c
WHERE c2g__InvoiceStatus__c = 'Complete'
AND LastModifiedDate = TODAY
LIMIT 5];
// Ensure there is at least one invoice to test
if (testInvoices.isEmpty()) {
System.debug('No invoices found with the status Complete and modified today.');
return;
}
// Create an instance of the batch class and call the execute method directly
Test.startTest();
ServicesBatch batch = new ServicesBatch();
Database.executeBatch(batch, 5);
Test.stopTest();
// Verify the results
Set<Id> accountIds = new Set<Id>();
for (c2g__codaInvoice__c invoice : testInvoices) {
if (invoice.c2g__Account__c != null) {
accountIds.add(invoice.c2g__Account__c);
}
}
List<Account> updatedAccounts = [SELECT Id, Last_Invoice_Date__c
FROM Account
WHERE Id IN :accountIds
AND Last_Invoice_Date__c != NULL];
System.assert(!updatedAccounts.isEmpty(), 'Accounts should have been updated with the latest invoice date');
// Additional assertions to check specific business logic if required
for (Account acc : updatedAccounts) {
Date latestInvoiceDate = null;
for (c2g__codaInvoice__c invoice : testInvoices) {
if (invoice.c2g__Account__c == acc.Id) {
Date invoiceDate = invoice.LastModifiedDate.date();
if (latestInvoiceDate == null || invoiceDate > latestInvoiceDate) {
latestInvoiceDate = invoiceDate;
}
}
}
System.assertEquals(latestInvoiceDate, acc.Last_Invoice_Date__c, 'The Last_Invoice_Date__c should match the latest invoice date for the account.');
}
}
@IsTest
static void testSchedulable() {
// Execute the scheduled job
Test.startTest();
ServicesBatch schedulable = new ServicesBatch();
String jobId = System.schedule('TestScheduledBatch', '0 0 0 * * ?', schedulable);
schedulable.execute(null);
Test.stopTest();
// Verify that the job has been scheduled
CronTrigger ct = [SELECT Id, CronExpression, TimesTriggered, NextFireTime
FROM CronTrigger WHERE Id = :jobId];
System.assertEquals('0 0 0 * * ?', ct.CronExpression);
System.assert(ct.NextFireTime != null, 'Scheduled job should have a next fire time');
}
}
This is the class its for
global class ServicesBatch implements Database.Batchable<sObject>, Schedulable {
String query;
global ServicesBatch() {
// Query to get all Sales Invoice records created today
query = 'SELECT Id, c2g__Account__c, c2g__InvoiceStatus__c, lastModifiedDate FROM c2g__codaInvoice__c WHERE lastModifiedDate = TODAY AND c2g__InvoiceStatus__c = \'Complete\'';
}
global Database.QueryLocator start(Database.BatchableContext BC) {
return Database.getQueryLocator(query);
}
global void execute(Database.BatchableContext BC, List<c2g__codaInvoice__c> scope) {
// Map to hold the latest invoice date for each Account
Map<Id, Date> accountInvoiceMap = new Map<Id, Date>();
// Iterate through the invoices in the current batch
for (c2g__codaInvoice__c invoice : scope) {
Date invoiceDate = invoice.lastModifiedDate.date();
if (invoice.c2g__Account__c != null) {
// Check if the account is already in the map
if (!accountInvoiceMap.containsKey(invoice.c2g__Account__c)) {
accountInvoiceMap.put(invoice.c2g__Account__c, invoiceDate);
} else {
// Update the date if this invoice is more recent
Date existingDate = accountInvoiceMap.get(invoice.c2g__Account__c);
if (invoiceDate > existingDate) {
accountInvoiceMap.put(invoice.c2g__Account__c, invoiceDate);
}
}
}
}
// List to hold the accounts to be updated
List<Account> accountsToUpdate = new List<Account>();
// Iterate through the map to create Account records with the latest invoice date
for (Id accountId : accountInvoiceMap.keySet()) {
Account acc = new Account(Id = accountId, Last_Invoice_Date__c = accountInvoiceMap.get(accountId));
accountsToUpdate.add(acc);
}
// Update the Account records
if (!accountsToUpdate.isEmpty()) {
update accountsToUpdate;
}
}
global void finish(Database.BatchableContext BC) {
// finish code
}
global void execute(SchedulableContext SC) {
if(!Test.isRunningTest()){
Database.executeBatch(new ServicesBatch());
}
}
}