0

I wrote a batch class that runs whenever a new sandbox is being refreshed. it takes all the contacts' email addresses and changes them from [email protected] to [email protected]. In addition, it checks whether the batch is being executed in production (i.e. the URL contains the eu3 (our production's server)),so if the BaseURL contains 'eu3' such as eu3.salesforce.com then it throws a custom exception.

The batch works, but I'm still struggling to write a test class that will get a high code coverage (currently I get 68%).

It seems that I cannot cover the Exception I wrote + the send email action at the finish method (see the screenshots).

global class changeEmailAddressesToExampleSandbox implements Database.Batchable<sObject>, Database.Stateful {

private List<Contact> contactsEmails;
private String tempEmail;
private String query;
//private Integer totalNumOfContacts;
private Integer total;
private Integer modified;

global changeEmailAddressesToExampleSandbox () {

    contactsEmails = new List<Contact>();
    query = 'SELECT email FROM Contact';
    tempEmail=' ';
    total = 0;
    modified = 0;
    //totalNumOfContacts=[select count() from contact]; //Too Many SOQL queries

}
global Database.QueryLocator start(Database.BatchableContext BC) {
    return Database.getQueryLocator(query);
}
global void execute(Database.BatchableContext BC, List<Contact> scope) { //changed Sobject to Contact

    String newEmailDomain = '@example.com';    

    // Check if it's production 
    String sfdcBaseURL = URL.getSalesforceBaseUrl().toExternalForm();
    System.debug('Base URL: ' + sfdcBaseURL );
   if(sfdcBaseURL.contains('eu3'))
      throw new ProductionException('Cannot execute code in production!'); 


    for (Contact con : scope){
        String tempEmail = con.Email;
        if(!String.isEmpty(tempEmail) && !tempEmail.contains('@example.com')&&tempEmail.length()<70){ //tempEmail.length<70 because STRING_TOO_LONG error
            tempEmail = tempEmail.split('@')[0];
            tempEmail += newEmailDomain;
            con.Email = tempEmail;
            contactsEmails.add(con);
        }
    }
    update contactsEmails;

    modified += contactsEmails.size();
    total += scope.size();
}
global void finish(Database.BatchableContext BC) {

    if (!Test.isRunningTest()){
    Messaging.SingleEmailMessage message = new Messaging.SingleEmailMessage();
    message.toAddresses = new String[] { '[email protected]'};
    message.optOutPolicy = 'FILTER';
    message.subject = 'Email From Batch class changeEmailAddressesToExampleInSandbox';
    message.plainTextBody = ''
    + 'All contacts\' emails have been modified successfully ' +'\n'
    + 'The total number of contacts in the Sandbox is '
    + total + '\n'
    + modified +' contacts were updated'
    ;
    Messaging.SingleEmailMessage[] messages =   new List<Messaging.SingleEmailMessage> {message};
    Messaging.SendEmailResult[] results = Messaging.sendEmail(messages);

    if (results[0].success) {
        System.debug('The email was sent successfully.');
        } else {
            System.debug('The email failed to send: ' + results[0].errors[0].message);
        }

    }
}
    public class ProductionException extends Exception {}
}

See Screenshots: Class part 1 Class part 2

Test Class:

@isTest

private class changeEmailAddressesToExampleSandboxTest {

@isTest static void test_positive() {
    Account acc = new Account(Name='Satyricon');
    insert acc;
    Contact con = new Contact(AccountId=acc.id,LastName='Satyr',Email='[email protected]');
    insert con;
    Test.startTest();
    changeEmailAddressesToExampleSandbox sandbox = new changeEmailAddressesToExampleSandbox();
    Database.executeBatch(sandbox);
    Test.stopTest();
    System.assertEquals('[email protected]',[SELECT email FROM Contact WHERE id=:con.id].email);




}

@isTest static void test_negative() {

    Test.startTest();
    String testURL = 'https://eu3.salesforce.com';
    Test.setCurrentPageReference(new PageReference(testURL));
    try{
    changeEmailAddressesToExampleSandbox sandbox = new changeEmailAddressesToExampleSandbox();
    Database.executeBatch(sandbox);
    }
    catch(Exception e){
        System.assert(e.getMessage().contains('Cannot execute code in production!'),e.getMessage());
    }
}

Can someone help me? How can I cover the Exception and the send email action in my test class?

1 Answer 1

1

For your first method you need some additional method or property to make it possible to substitute production URL for test

@testVisible static String baseURL { get {
    if ( baseURL == null )
        baseURL = URL.getSalesforceBaseUrl().toExternalForm();
    return baseURL;
} set; }


global void execute(Database.BatchableContext BC, List<Contact> scope) { //changed Sobject to Contact

String newEmailDomain = '@example.com';    

// Check if it's production 
System.debug('Base URL: ' + baseURL );
if(baseURL.contains('eu3'))
  throw new ProductionException('Cannot execute code in production!'); 


for (Contact con : scope){
    String tempEmail = con.Email;
    if(!String.isEmpty(tempEmail) && !tempEmail.contains('@example.com')&&tempEmail.length()<70){ //tempEmail.length<70 because STRING_TOO_LONG error
        tempEmail = tempEmail.split('@')[0];
        tempEmail += newEmailDomain;
        con.Email = tempEmail;
        contactsEmails.add(con);
    }
}
update contactsEmails;

modified += contactsEmails.size();
total += scope.size();

}

Then in your test you can create a separate method to cover exceptional case

@isTest static void test_negative() {

Test.startTest();
changeEmailAddressesToExampleSandbox.baseURL = 'https://eu3.salesforce.com';
try{
changeEmailAddressesToExampleSandbox sandbox = new changeEmailAddressesToExampleSandbox();
Database.executeBatch(sandbox);
}
catch(Exception e){
    System.assert(e.getMessage().contains('Cannot execute code in production!'),e.getMessage());
}
}

Also you should remove check if (!Test.isRunningTest()){ in your finish method, otherwise you wouldn't get coverage for those lines

global void finish(Database.BatchableContext BC) {
Messaging.SingleEmailMessage message = new Messaging.SingleEmailMessage();
message.toAddresses = new String[] { '[email protected]'};
message.optOutPolicy = 'FILTER';
message.subject = 'Email From Batch class changeEmailAddressesToExampleInSandbox';
message.plainTextBody = ''
+ 'All contacts\' emails have been modified successfully ' +'\n'
+ 'The total number of contacts in the Sandbox is '
+ total + '\n'
+ modified +' contacts were updated'
;
Messaging.SingleEmailMessage[] messages =   new List<Messaging.SingleEmailMessage> {message};
Messaging.SendEmailResult[] results = Messaging.sendEmail(messages);

if (results[0].success) {
    System.debug('The email was sent successfully.');
    } else {
        System.debug('The email failed to send: ' + results[0].errors[0].message);
    }

}

Please mark this answer as accepted if this helps you. Thanks.

2
  • thank you for your help. Your suggestion to remove the !Test.isRunningTest() was excellent, code coverage is now 97%. However, I still get a red line on the ProductionException.
    – Json
    Dec 14, 2016 at 11:37
  • I have updated my answer, please try the updated code
    – Patlatus
    Dec 14, 2016 at 12:03

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .