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
Michael Hedrick 2Michael Hedrick 2 

Test code for

Hello All,
I have been going in circles with this code for 2 days and received some help but I am still at a loss.  The code below looks for Contracts where the checkbox Automatic_renewal__c = TRUE AND the field Contract_End_Date_Current__c = Yesterday.  I have tried to create a test class with data  but my test coverage is '0'.  All of the Contracts are associated to an Account.  So can I jsut have a single account with multiple Contracts assoicated to it?  What is the best way to confirm that the contract data was created with the desired date?  
Any help would be greatly appreciated.
Cheers,
M

 Global class ContractUpdateContractRenewalStartDate implements Schedulable {
    // Allow tests to see the variable, but not "normal" code
    @TestVisible Date contractdate = System.today().addDays(-1);
       
        global void execute(SchedulableContext sc) {
         list<Contract> Contractupdate = [SELECT Id, Contract_Start_Date_Current__c,Contract_End_Date_Current__c FROM Contract WHERE              Automatic_renewal__c = TRUE AND Contract_End_Date_Current__c =: contractdate ];
       
         for(Contract c: Contractupdate)
       {
            c.Contract_Start_Date_Current__c = System.today();
        }
        update Contractupdate;
    } 
}
Best Answer chosen by Michael Hedrick 2
Mahesh DMahesh D
Hi Michael,

I would recommend you to write the code using Batch Apex as we are not sure about the number of records it will return. Hence use the below code:

Here I considered:


 ==> Corrected the Code.
==> Implemented the Test Class
==> Tested the code in DE environment.
/*
* Name          : ContractUpdateBatch
* Version       : 1.0
* Created Date  : 
* Author        : 
* Description   : Batch Apex to update the Contract Renewal Start Date.
* History       : 
*        
*/

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

    //Variable Section
    global FINAL String strQuery;
    global List<String> errorMessages = new List<String>();
    global Date contractdate = System.today().addDays(-1);
    
    global ContractUpdateBatch() { 
        this.strQuery = getBatchQuery();
    }
    
    //Returns the Query String to Batch constructor to fetch right records.
    private String getBatchQuery() {
        String strQuery = 'SELECT Id, Contract_Start_Date_Current__c, Contract_End_Date_Current__c FROM Contract WHERE Automatic_renewal__c = TRUE AND Contract_End_Date_Current__c =: contractdate'; 
        return strQuery;
    }
    
    //Batch Start method
    global Database.QueryLocator start(Database.BatchableContext BC) {
        return Database.getQueryLocator(strQuery);
    }

    //Batch Execute method calls findCostForWoD method
    global void execute(Database.BatchableContext BC, List<sObject> scopeList) {
        System.debug(LoggingLevel.INFO, '== scopeList size ==' + scopeList.size());
        
        List<Contract> contList = (List<Contract>) scopeList;
        
        for(Contract cont: contList) {
            cont.Contract_Start_Date_Current__c = System.today();
        }
        
        try {                    
            Database.SaveResult[] saveResults = Database.update(contList, false);
            for (Database.SaveResult sr : SaveResults) {
                if(!sr.isSuccess()) {
                    for (Database.Error err : sr.getErrors()) {
                        errorMessages.add('Error: ' + err.getStatusCode() + ': ' + err.getMessage());
                    }
                    system.debug(sr.getErrors()[0].getMessage());
                }
            }
            System.debug('errorMessages: '+errorMessages);
        } catch (System.Exception ex) {
            System.debug('An error occurred when updating Contracts: ' + ex.getMessage());
            return;
        }
    }  

    //Batch Finish method for after execution of batch work
    global void finish(Database.BatchableContext BC) { 
        AsyncApexJob aaj = [Select Id, Status, NumberOfErrors, JobItemsProcessed, MethodName, TotalJobItems, CreatedBy.Email from AsyncApexJob where Id =:BC.getJobId()];
        
        // Send an email to the Apex job's submitter notifying of job completion.
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        String[] toAddresses = new String[] {aaj.CreatedBy.Email};
        mail.setToAddresses(toAddresses);
        mail.setSubject('JOB Salesforce ContractUpdateBatch: ' + aaj.Status);
        String bodyText='Total Job Items ' + aaj.TotalJobItems + ' Number of records processed ' + aaj.JobItemsProcessed + ' with '+ aaj.NumberOfErrors + ' failures.\n';
        bodyText += 'Number of Error Messages ' + errorMessages.size() + '\n';
        bodyText += 'Error Message' + String.join(errorMessages, '\n');
        mail.setPlainTextBody(bodyText);
        Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
    }
    
    //Method which schedules the ContractUpdateBatch
    global void execute(SchedulableContext sc) {        
        ContractUpdateBatch cub = new ContractUpdateBatch();
        ID batchprocessid = Database.executeBatch(cub);
    }
}

Also Tested the code in my DE environment and it looks good.

Below is the Test Class:

 
@isTest
public class ProductDownloadBatchTest {
    public static String CRON_EXP = '0 0 1 * * ?';
    
    static testmethod void testProductDownloadBatchFromPH() {
        
        Account acc = new Account();
        acc.Name='Test Acc';
        insert acc;

        Contract con = new Contract();
        con.AccountId = acc.id;
        con.Contract_End_Date_Current__c = System.today().addDays(-1);
        con.Automatic_renewal__c = TRUE;
        insert con;
        
        test.StartTest();  
        String jobId = System.schedule('ScheduleApexClassTest', CRON_EXP, new ContractUpdateBatch());
        
        CronTrigger ct = [SELECT id, CronExpression, TimesTriggered, NextFireTime FROM CronTrigger WHERE id = :jobId];
        System.assertEquals(CRON_EXP, ct.CronExpression);
        System.assertEquals(0, ct.TimesTriggered);
        Test.stopTest();
    }
}

Also Verified the code coverage:

User-added image


Please do let me know if it helps you.

Regards,
Mahesh

 

All Answers

Amit Chaudhary 8Amit Chaudhary 8
Please try below code.
@isTest
private class ContractUpdateContractRenewalStartTest 
{

   public static String CRON_EXP = '0 0 0 15 3 ? 2022';

   static testmethod void test() 
   {
	Account a = new Account();
    a.Name='a';
	insert a;

    Contract c = new Contract ();
    c.AccountId = a.id;
    c.status = 'Signed';
	c.Contract_End_Date_Current__c=System.today().addDays(-1);
	c. Automatic_renewal__c = TRUE;
    insert c;
	
      String jobId = System.schedule('ScheduleApexClassTest', CRON_EXP, new ContractUpdateContractRenewalStartDate() );
      CronTrigger ct = [SELECT Id, CronExpression, TimesTriggered,   NextFireTime  FROM CronTrigger WHERE id = :jobId];
      System.assertEquals(CRON_EXP,  ct.CronExpression);

   }
}
Let us know if this will help you

 
Mahesh DMahesh D
Hi Michael,

I would recommend you to write the code using Batch Apex as we are not sure about the number of records it will return. Hence use the below code:

Here I considered:


 ==> Corrected the Code.
==> Implemented the Test Class
==> Tested the code in DE environment.
/*
* Name          : ContractUpdateBatch
* Version       : 1.0
* Created Date  : 
* Author        : 
* Description   : Batch Apex to update the Contract Renewal Start Date.
* History       : 
*        
*/

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

    //Variable Section
    global FINAL String strQuery;
    global List<String> errorMessages = new List<String>();
    global Date contractdate = System.today().addDays(-1);
    
    global ContractUpdateBatch() { 
        this.strQuery = getBatchQuery();
    }
    
    //Returns the Query String to Batch constructor to fetch right records.
    private String getBatchQuery() {
        String strQuery = 'SELECT Id, Contract_Start_Date_Current__c, Contract_End_Date_Current__c FROM Contract WHERE Automatic_renewal__c = TRUE AND Contract_End_Date_Current__c =: contractdate'; 
        return strQuery;
    }
    
    //Batch Start method
    global Database.QueryLocator start(Database.BatchableContext BC) {
        return Database.getQueryLocator(strQuery);
    }

    //Batch Execute method calls findCostForWoD method
    global void execute(Database.BatchableContext BC, List<sObject> scopeList) {
        System.debug(LoggingLevel.INFO, '== scopeList size ==' + scopeList.size());
        
        List<Contract> contList = (List<Contract>) scopeList;
        
        for(Contract cont: contList) {
            cont.Contract_Start_Date_Current__c = System.today();
        }
        
        try {                    
            Database.SaveResult[] saveResults = Database.update(contList, false);
            for (Database.SaveResult sr : SaveResults) {
                if(!sr.isSuccess()) {
                    for (Database.Error err : sr.getErrors()) {
                        errorMessages.add('Error: ' + err.getStatusCode() + ': ' + err.getMessage());
                    }
                    system.debug(sr.getErrors()[0].getMessage());
                }
            }
            System.debug('errorMessages: '+errorMessages);
        } catch (System.Exception ex) {
            System.debug('An error occurred when updating Contracts: ' + ex.getMessage());
            return;
        }
    }  

    //Batch Finish method for after execution of batch work
    global void finish(Database.BatchableContext BC) { 
        AsyncApexJob aaj = [Select Id, Status, NumberOfErrors, JobItemsProcessed, MethodName, TotalJobItems, CreatedBy.Email from AsyncApexJob where Id =:BC.getJobId()];
        
        // Send an email to the Apex job's submitter notifying of job completion.
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        String[] toAddresses = new String[] {aaj.CreatedBy.Email};
        mail.setToAddresses(toAddresses);
        mail.setSubject('JOB Salesforce ContractUpdateBatch: ' + aaj.Status);
        String bodyText='Total Job Items ' + aaj.TotalJobItems + ' Number of records processed ' + aaj.JobItemsProcessed + ' with '+ aaj.NumberOfErrors + ' failures.\n';
        bodyText += 'Number of Error Messages ' + errorMessages.size() + '\n';
        bodyText += 'Error Message' + String.join(errorMessages, '\n');
        mail.setPlainTextBody(bodyText);
        Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
    }
    
    //Method which schedules the ContractUpdateBatch
    global void execute(SchedulableContext sc) {        
        ContractUpdateBatch cub = new ContractUpdateBatch();
        ID batchprocessid = Database.executeBatch(cub);
    }
}

Also Tested the code in my DE environment and it looks good.

Below is the Test Class:

 
@isTest
public class ProductDownloadBatchTest {
    public static String CRON_EXP = '0 0 1 * * ?';
    
    static testmethod void testProductDownloadBatchFromPH() {
        
        Account acc = new Account();
        acc.Name='Test Acc';
        insert acc;

        Contract con = new Contract();
        con.AccountId = acc.id;
        con.Contract_End_Date_Current__c = System.today().addDays(-1);
        con.Automatic_renewal__c = TRUE;
        insert con;
        
        test.StartTest();  
        String jobId = System.schedule('ScheduleApexClassTest', CRON_EXP, new ContractUpdateBatch());
        
        CronTrigger ct = [SELECT id, CronExpression, TimesTriggered, NextFireTime FROM CronTrigger WHERE id = :jobId];
        System.assertEquals(CRON_EXP, ct.CronExpression);
        System.assertEquals(0, ct.TimesTriggered);
        Test.stopTest();
    }
}

Also Verified the code coverage:

User-added image


Please do let me know if it helps you.

Regards,
Mahesh

 
This was selected as the best answer
Michael Hedrick 2Michael Hedrick 2
Thank you both so much for your effort and time.  I will look at your examples today.  I forgot to state that the Contract_End_Date_Current__c field is a formula field based on the Contract_Start_Date_Current__c and Contract_Renewal_Terms__c(numeric value more months).
I will add the 2 additional fields when I create the contract and hopefully it will work...
Kind Regards,
M
Michael Hedrick 2Michael Hedrick 2
Thank you both for your help.  Code is deployed to production.  Can I not assign you both as supplying the correct answer since you both are correct and your answers were very helpful?  Mahesh, greatly appreciate the annotation. As a novice reviewing the different approaches one takes to solve a problem the annotation is very helpful in understanding the logic.
Cheers,
Michael