+ Start a Discussion
Jeff JobsJeff Jobs 

Can't get Code Coverage on Variable Updates

Hi,
I'm trying to create some Date Logic in an Apex Class.  Everything I do works exactly how I want, but I can't get coverage on part of the code no matter what I try.  I've included a screenshot:
User-added image
Essentially I'm trying to create two date variables "nextPayDay" and "nextClosingPayDay" based on date fields that are found on my payout object (p).  I include a scenario in my test class where the month + 1 ends up being January (1) and when I do a system.assertEquals, I can see that the year has gone up by 1.  However, it is still red in the test class.  Any help would be greatly appreciated!
 
Best Answer chosen by Jeff Jobs
James LoghryJames Loghry
Jeff, unless I'm missing something, you are not setting "Cha_Ching_Date__c" anywhere in your test code.  Nor are you setting it in your trigger or utility method.  So all your checks that have anything to do with Cha_Ching_Date__c will not pass, and hence I believe is why you're not seeing test code coverage for those.

Additionally, in at least one of your test cases (you should have multiple test cases because there is a lot of logic in your trigger and utility class), you should set the Cha Ching Date to December, to catch the "NextMonth+1" logic.

Here's an example where I would set the Cha Ching Date to December.  I've also added your juniorBonus1 to a list, to show how you would insert multiple records at the same time for your test class.
List<Payout__c> payoutsToInsert = new List<Payout__c>();

Payout__c juniorBonus1 = new Payout__c(
    OwnerId = currentUser.Id
    ,Account__c = JeffPayroll.Id
    ,Opportunity__c = Scenario1.Id
    ,Property__c = PayrollSt.Id
    ,Junior_Deal__c = TRUE
    ,Junior_Bonus__c = TRUE
    //Adding the Cha Ching Date of December, 2013 to ensure the nextMonth+1 logic is correct
    ,Cha_Ching_Date__c = Date.newInstance(2013, 12, 31)
);
payouts.add(payoutsToInsert);
        

Payout__c juniorCommission1 = new Payout__c(
    //juniorCommissionFields go here
);
payouts.add(juniorCommission1);
insert payouts;

 

All Answers

James LoghryJames Loghry
Code doesn't lie :)  It's likely your logic is still incorrect.  Are you working with mulitple Payout__c records?  Is it possible your month is correct for one of the records, but incorrect for the last record, throwing off your nextMonth and closingMonth if checks?  Would help if you could post the rest of your class along with the test class.
Jeff JobsJeff Jobs
Thanks James :)  I'm certainly not disputing the results, just trying to figure out how to get it covered.  Here is my entire test class so far; I'll also post my trigger and utility class next:

@isTest

public class PayrollTester {

    public static testMethod void standardTest() {
        
        //Scenario 1a - After Cha-Ching/Junior Rep/Current Structure/No Rent Spread/
        //Listing - Active (or NULL)/Not Commission-Only
        
        //Example Data
        //Insert Jeff Payroll Account
        RecordType rt = [SELECT Id FROM RecordType WHERE SObjectType = 'Account' AND Name LIKE '%Person%' LIMIT 1];
        
        Account JeffPayroll = new Account();
        
        JeffPayroll.RecordTypeId = rt.Id;
        JeffPayroll.LastName = 'Test';
        
        insert JeffPayroll;
        
        //Get Current User
        User currentUser = [SELECT Id, Senior_Solutions_Consultant__c
                            FROM User
                            WHERE ProfileId = '00ed0000000yEks'
                            AND IsActive = TRUE
                            LIMIT 1];
        
        currentUser.Senior_Solutions_Consultant__c = FALSE;
        update currentUser;
        
        //Insert Scenario 1 Opportunity
        rt = [SELECT Id FROM RecordType WHERE SObjectType = 'Opportunity' AND Name LIKE '%Home%' LIMIT 1];
        
        Opportunity Scenario1 = new Opportunity();
        
        Scenario1.RecordTypeId = rt.Id;
        Scenario1.OwnerId = currentUser.Id;
        Scenario1.AccountId = JeffPayroll.Id;
        Scenario1.Name = 'Test';
        Scenario1.StageName = 'Test';
        Scenario1.CloseDate = System.today();
        Scenario1.FMV_New__c = 1000;
        Scenario1.MPH_Rent_to_Offer__c = 1000;
        Scenario1.Cha_Ching__c = TRUE;
        Scenario1.Cha_Ching_Date_v2__c = Date.parse('11/05/2014');
        Scenario1.Actual_Commission_NEW__c = 10000;
        Scenario1.Closing_Date__c = Date.parse('03/12/2015');
        
        insert Scenario1;
        
        Opportunity Scenario1c = new Opportunity();
        
        Scenario1c.RecordTypeId = rt.Id;
        Scenario1c.OwnerId = currentUser.Id;
        Scenario1c.AccountId = JeffPayroll.Id;
        Scenario1c.Name = 'Test';
        Scenario1c.StageName = 'Test';
        Scenario1c.CloseDate = System.today();
        Scenario1c.FMV_New__c = 1000;
        Scenario1c.MPH_Rent_to_Offer__c = 1000;
        Scenario1c.Cha_Ching__c = TRUE;
        Scenario1c.Cha_Ching_Date_v2__c = Date.parse('08/05/2014');
        Scenario1c.Actual_Commission_NEW__c = 10000;
        Scenario1c.Closing_Date__c = Date.parse('03/12/2015');
        
        insert Scenario1c;
        
        //Insert Payroll St Property
        Property__c PayrollSt = new Property__c();
        
        PayrollSt.Name = '123 Payroll St';
        PayrollSt.Address_Line_1__c = '123 Payroll St';
        PayrollSt.Home_Sale_Opportunity__c = Scenario1.Id;
        
        insert PayrollSt;
        
        //Insert Active Listing
        Listing__c active = new Listing__c();
        
        active.Name = 'Test';
        active.Property__c = PayrollSt.Id;
        active.Listing_Status__c = 'Active';
        
        insert active;
        
        Scenario1.Listing__c = active.Id;
        update Scenario1;
        
        //Expected Result
        //New payout record created with a commission of: $250.00 and a payout date of: 12/15/2014
        //New payout record created with a commission of: $800.00 and a payout date of: 04/15/2015
        
        //Simulate Cha-Ching FLOW
        Payout__c juniorBonus1 = new Payout__c();
        
        juniorBonus1.OwnerId = currentUser.Id;
        juniorBonus1.Account__c = JeffPayroll.Id;
        juniorBonus1.Opportunity__c = Scenario1.Id;
        juniorBonus1.Property__c = PayrollSt.Id;
        juniorBonus1.Junior_Deal__c = TRUE;
        juniorBonus1.Junior_Bonus__c = TRUE;
        
        insert juniorBonus1;
        
        Payout__c juniorCommission1 = new Payout__c();
        
        juniorCommission1.OwnerId = currentUser.Id;
        juniorCommission1.Account__c = JeffPayroll.Id;
        juniorCommission1.Opportunity__c = Scenario1.Id;
        juniorCommission1.Property__c = PayrollSt.Id;
        juniorCommission1.Junior_Deal__c = TRUE;
        
        insert juniorCommission1;
        
        //Check Results
        juniorBonus1 = [SELECT Id, Commission_Amount__c, Payout_Date__c FROM Payout__c WHERE Id = :juniorBonus1.Id];
        juniorCommission1 = [SELECT Id, Commission_Amount__c, Payout_Date__c FROM Payout__c WHERE Id = :juniorCommission1.Id];
        
        System.assertEquals(250, juniorBonus1.Commission_Amount__c);
        System.assertEquals(Date.parse('12/15/2014'), juniorBonus1.Payout_Date__c);
        System.assertEquals(800, juniorCommission1.Commission_Amount__c);
        System.assertEquals(Date.parse('04/15/2015'), juniorCommission1.Payout_Date__c);
        
       //From here on down, I am taking stabs at trying to get those lines covered
        Scenario1.Cha_Ching_Date_v2__c = Date.parse('12/22/2014'); //The Payout object has formula fields which display this from the Opp
        Scenario1.Closing_Date__c = Date.parse('12/22/2014'); //The Payout object has formula fields which display this from the Opp
        update Scenario1;
        update juniorBonus1;
        update juniorCommission1;
        
        //Check Results
        juniorBonus1 = [SELECT Id, Payout_Date__c FROM Payout__c WHERE Id = :juniorBonus1.Id];
        juniorCommission1 = [SELECT Id, Payout_Date__c FROM Payout__c WHERE Id = :juniorCommission1.Id];
        
        System.assertEquals(Date.parse('01/15/2015'), juniorBonus1.Payout_Date__c);
        System.assertEquals(Date.parse('01/15/2015'), juniorCommission1.Payout_Date__c);
        System.assertEquals(2015, juniorBonus1.Payout_Date__c.Year());

//there will be more to write for Scenario 1b and 1c after I figure this out
Jeff JobsJeff Jobs
utility class:

public class CommissionPayoutBusinessLogic {

    //Scenario 1a - After Cha-Ching/Junior Rep/Current Structure/No Rent Spread/
    //Listing - Active (or NULL)/Not Commission-Only
    public static void scenario1A(List<Payout__c> scenario1A) {
        
        //Instance Variables
        Integer nextMonth;
        Integer year;
        Date nextPayDay;
        Integer closingMonth;
        Integer closingDay;
        Integer closingYear;
        Date nextClosingPayDay;
                
        //Begin Date Logic            
        for(Payout__c p :scenario1A) {
        
            nextMonth = p.Cha_Ching_Date__c.Month() + 1;
            year = p.Cha_Ching_Date__c.Year();
            closingMonth = p.Closing_Date__c.Month() + 1;
            closingDay = p.Closing_Date__c.Day();
            closingYear = p.Closing_Date__c.Year();
        }
        
        //Account for Next Pay Day December/January Year Change
        if(nextMonth == 1) {
            
            year += 1;
        }
        
        //Account for Closing Pay Day December/January Year Change
        if(closingMonth == 1) {
            
            closingYear += 1;
        }
        
        //Create a Payout Date for Next Month on the 15th
        nextPayDay = Date.newInstance(year, nextMonth, 15);
        
        //Create a Closing Payout Date based on the Closing Date Logic
        nextClosingPayDay = Date.newInstance(closingYear, closingMonth, 15);
                
        for(Payout__c p : scenario1A) {
            
            if(p.Junior_Bonus__c == TRUE) {
                
                p.Commission_Amount__c = 250;
                p.Payout_Date__c = nextPayDay;
            }
            
            if(p.Junior_Bonus__c == FALSE) {
                
                p.Commission_Amount__c = (((p.Estimated_Commission__c - 3000) * .15) - 250).setScale(2);
                p.Payout_Date__c = nextClosingPayDay;
            }
        }
    }
}
Jeff JobsJeff Jobs
Trigger:

trigger PayoutRouter on Payout__c (before insert, before update) {

    //Instance Variables
    Date currentStructure = Date.Parse('09/01/2014');
    List<Payout__c> scenario1A = new List<Payout__c>();
    List<Payout__c> scenario1B = new List<Payout__c>();
    
    if(Trigger.isBefore) {
    
        if(Trigger.isInsert) {
        
            for(Payout__c p :Trigger.new) {
                
                //Scenario 1A
                if(p.Cha_Ching_Date__c > currentStructure && (p.FMV__c - p.GLA__c) == 0
                   && p.Closed_Listing__c == FALSE && p.Commission_Only__c == FALSE
                   && p.Builder_Commission_Received__c == FALSE) {
                       
                       scenario1A.add(p);
                   }
                
                //Scenario 1A
                if(p.Cha_Ching_Date__c > currentStructure && (p.FMV__c - p.GLA__c) == 0
                   && p.Closed_Listing__c == FALSE && p.Commission_Only__c == FALSE
                   && p.Builder_Commission_Received__c == TRUE) {
                       
                       scenario1B.add(p);
                   }
            }
            
            CommissionPayoutBusinessLogic.scenario1A(scenario1A);
            CommissionPayoutBusinessLogic.scenario1B(scenario1B);
        }
        
        if(Trigger.isUpdate) {
        
            for(Payout__c p :Trigger.new) {
                
                //Scenario 1A
                if(p.Cha_Ching_Date__c > currentStructure && (p.FMV__c - p.GLA__c) == 0
                   && p.Closed_Listing__c == FALSE && p.Commission_Only__c == FALSE
                   && p.Builder_Commission_Received__c == FALSE) {
                       
                       scenario1A.add(p);
                   }
                
                //Scenario 1B
                if(p.Cha_Ching_Date__c > currentStructure && (p.FMV__c - p.GLA__c) == 0
                   && p.Closed_Listing__c == FALSE && p.Commission_Only__c == FALSE
                   && p.Builder_Commission_Received__c == TRUE) {
                       
                       scenario1B.add(p);
                   }
            }
            
            CommissionPayoutBusinessLogic.scenario1A(scenario1A);
            CommissionPayoutBusinessLogic.scenario1B(scenario1B);
        }
    }
}
Jeff JobsJeff Jobs
I realize that 1b is not in the utility class I posted, but it is there and is what I'm working on currently so I didn't post the incomplete method.
Jeff JobsJeff Jobs
1A is the one that is not testing at 100%
James LoghryJames Loghry
Jeff, unless I'm missing something, you are not setting "Cha_Ching_Date__c" anywhere in your test code.  Nor are you setting it in your trigger or utility method.  So all your checks that have anything to do with Cha_Ching_Date__c will not pass, and hence I believe is why you're not seeing test code coverage for those.

Additionally, in at least one of your test cases (you should have multiple test cases because there is a lot of logic in your trigger and utility class), you should set the Cha Ching Date to December, to catch the "NextMonth+1" logic.

Here's an example where I would set the Cha Ching Date to December.  I've also added your juniorBonus1 to a list, to show how you would insert multiple records at the same time for your test class.
List<Payout__c> payoutsToInsert = new List<Payout__c>();

Payout__c juniorBonus1 = new Payout__c(
    OwnerId = currentUser.Id
    ,Account__c = JeffPayroll.Id
    ,Opportunity__c = Scenario1.Id
    ,Property__c = PayrollSt.Id
    ,Junior_Deal__c = TRUE
    ,Junior_Bonus__c = TRUE
    //Adding the Cha Ching Date of December, 2013 to ensure the nextMonth+1 logic is correct
    ,Cha_Ching_Date__c = Date.newInstance(2013, 12, 31)
);
payouts.add(payoutsToInsert);
        

Payout__c juniorCommission1 = new Payout__c(
    //juniorCommissionFields go here
);
payouts.add(juniorCommission1);
insert payouts;

 
This was selected as the best answer
Jeff JobsJeff Jobs
James,

Thanks for pointing that out.  The p.Cha_Ching_Date__c field is a formula that pulls the info from Opportunity.Cha_Ching_Date_v2__c (which is referenced), however since my test class is taking me literally as you just did, that's probably the issue.  Thanks very much for your input.  I will modify my code today and post back with my results.  You've given me exactly what I needed, a cause of the problem!
Jeff JobsJeff Jobs
James,

HA!  That was it!!  Additionally, 12 + 1 = 13, so I needed to adjust my class accordingly. 

//Account for Next Pay Day December/January Year Change
        if(nextMonth == 13) {
            
            nextMonth = 1;
            year += 1;
        }

Thanks a lot!
James LoghryJames Loghry
Actually, you were on the right track the first time.

The next month should be "1" not "13", but instead of simply saying month + 1, you should use the Date class's "addMonths()" method.

For example:
for(Payout__c p :scenario1A) {
    nextMonth = p.Cha_Ching_Date__c.addMonths(1).Month();
    year = p.Cha_Ching_Date__c.Year();
    closingMonth = p.Closing_Date__c.addMonths(1).Month();
    closingDay = p.Closing_Date__c.Day();
    closingYear = p.Closing_Date__c.Year();
}

For more on the Date class, see here: https://www.salesforce.com/us/developer/docs/apexcode/Content/apex_methods_system_date.htm#apex_System_Date_addMonths