function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
LoganMooreLoganMoore 

Testing a method that only works with objects older than 2 minutes

Here's an interesting test that I need to work out.

The method sendConfirmations in this class gets a list of deals older than two minutes and sends a confirmation email to the customer (I've got it hard coded to send to me while I'm testing it). The reason for this delay is that there's an external system that takes a little while to insert all of the information and related objects under this deal. This method is then scheduled to run every 5 minutes.

Because I only query deals older than 2 minutes, I can't create objects to test, as the new objects are not older than 2 minutes, so they aren't seen.

How can I get around this and test the method without relying on existing objects in the salesforce?

global class ConfirmationsScheduledSend implements Schedulable {
	
	global void execute(SchedulableContext sc) {
		sendConfirmations();
	}
	
	global static void sendConfirmations() {
		Id template = '00XD0000001WNxW';
		String debugEmail = 'logan.moore@velocitytrade.co.nz';
		Boolean debugEnabled = true;
		
		// We need to ensure that we've given felix enough time to upload any
		// outgoing payment information, so we only want to query deals older than 2 minutes
		Datetime twoMinutesAgo = Datetime.now().addMinutes(-2);
		List<Deal__c> deals = [SELECT Id, Felix_Trading_Account__r.OwnerId, Felix_Trading_Account__r.Contact__c FROM Deal__c WHERE Send_Confirmation_Flag__c = true AND CreatedDate < :twoMinutesAgo];
		
		// We're also going to need a list of all salesforce users, as we
		// will be blind carbon copying the owner in on all of their auto confirmations.
		Map<Id,User> users = new Map<ID,User>([Select Id, Name, Email FROM User]);
		
		// Set up the email queue and reserve email capacity
		List<Messaging.SingleEmailMessage> emailQueue = new List<Messaging.SingleEmailMessage>();
		Messaging.reserveSingleEmailCapacity( users.size() );
		
		for (Deal__c deal : deals) {
			// Figure out the deal owner
			User owner = users.get(deal.Felix_Trading_Account__r.OwnerId);
			
			// Compiling a list of BCCs for this email
			List<String> bccList = new List<String>();
			//bccList.add(String.valueOf(owner.Email)); // bcc the owner in all cases
			if (debugEnabled)
				bccList.add('logan.moore@velocitytrade.com');
			
			// Build up the email message object
			Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
			email.setTemplateID(template);
			email.setWhatId(deal.Id);
			//email.setTargetObjectId(deal.Felix_Trading_Account__r.Contact__c);
			email.setSaveAsActivity(false);
			email.setTargetObjectId('00520000001ZoRC');
			email.setBccAddresses(bccList);
			emailQueue.add(email);
			
			// now that the email is queued, we remove the flag and set the last send datetime.
			deal.Send_Confirmation_Flag__c = false;
			deal.Last_Confirmation_Sent__c = Datetime.now();
		}
		
		// Try sending the email in a try-catch block. If something goes wrong, I NEED to know about it ASAP.
		try {
			if (emailQueue.size() > 0) {
				Messaging.sendEmail(emailQueue);
			}
			update deals;
		}
		catch (EmailException ex) {
			Messaging.SingleEmailMessage errorEmail = new Messaging.SingleEmailMessage();
			errorEmail.setToAddresses(new List<String>{ debugEmail });
			errorEmail.setSubject('ALERT: Confirmations Email Failed');
			errorEmail.setPlainTextBody('HIGH PRIORITY ALERT:\n\nThere was an error trying to send automatic confirmations. The error reads as follows:\n\n' + ex);
			Messaging.sendEmail(new List<Messaging.SingleEmailMessage>{ errorEmail });
		}
	}
	
}

 



 

Best Answer chosen by Admin (Salesforce Developers) 
WizradWizrad

I would do the following:

 

1) Create the data needed in the unit test.  Always.

 

2) I would just cheat and change my code to the following:

 

Datetime twoMinutesAgo = Test.isRunningTest() ? Datetime.now() : Datetime.now().addMinutes(-2);