[SalesForce] Unit test apex trigger not populating picklist values

I have simple 'after insert' trigger on a custom object to update picklist values. Based on some IF conditions I am updating picklist values which is perfectly working fine from webservice or manual insert from UI but when I write unit test case for it then it always return null for picklist values. Picklist values are dependent on Trigger execution after the record is inserted. I am not controlling picklist values. I am creating test data and it is returning values for all fields excepting picklist values. Do I need to set values explicitly?
Here is the code:
Trigger:

trigger UpdateLeaseInfo on Lease__c (after insert){
    List<Lease__c> listOfLease = new List<Lease__c>();
    for ( Lease__c updateLease : Trigger.New ) {
        if ( updateLease.contract__c == 'New' )
            updateLease.status__c = 'Pending Approval'; //status__c is picklist
        else 
            updateLease.status__c = 'Lease in Review';
        listOfLease.add(updateLease);
    }
    update listOfLease;
    }
}

Test Class:

@isTest
public class UpdateLeaseInfoTest {
    public UpdateLeaseInfoTest() {}
    static Lease__c createTestData() {
        // Expect to set the value of status__c automatically as trigger executes.
        Lease__c testData = new Lease__c(contract__c = 'New', FirstName__c='ABC', LastName__c = 'XYZ', LLID='ABCD1234'); 
        insert testData;
        return testData;
    }
    static void testUpdateLeaseInfo() {
        Lease__c lease = createTestData();
        System.test.startTest();
            System.assertEquals('Pending Approval', lease.status__c);
        System.test.stopTest();
    }
}

Assert returns Null values for lease.status__c.

Best Answer

All that you are missing in the test class is that you need to re-soql for the Lease. The CreateTestData method has a reference to the record with status=null before it inserts. Once it inserts, status is still null in the sobject in memory, but the database will have the correct status. Do this instead and you should be good.

@isTest
public class UpdateLeaseInfoTest {
    public UpdateLeaseInfoTest() {}
    static Lease__c createTestData() {
        // Expect to set the value of status__c automatically as trigger executes.
        Lease__c testData = new Lease__c(contract__c = 'New', FirstName__c='ABC', LastName__c = 'XYZ', LLID='ABCD1234'); 
        insert testData;
        //SOQL for transformed record, fresh from DB after all triggers, workflow etc.
        testData = [SELECT contract__c, FirstName__c, LastName__c, LLID, status__c FROM Lease__c WHERE id =: testData.id]; 
        return testData;
    }
    static void testUpdateLeaseInfo() {
        Lease__c lease = createTestData();
        System.test.startTest();
            System.assertEquals('Pending Approval', lease.status__c);
        System.test.stopTest();
    }
}

** ALSO I would highly recommend that you change to a Before Insert trigger. It will save you an uneccessary DML operation. If you are typically making changes to the record being triggered you can do it in a before trigger. It's definitely a best practice and prevents recursive trigger execution. It would look like this:

trigger UpdateLeaseInfo on Lease__c (before insert){

    for ( Lease__c updateLease : Trigger.New ) {
        if ( updateLease.contract__c == 'New' )
            updateLease.status__c = 'Pending Approval'; //status__c is picklist
        else 
            updateLease.status__c = 'Lease in Review';
    }
}

** Finally, the logic and field change operation that you are doing here is simple enough to be a workflow rule. No code, no unit test needed. Just a thought, I'm sure there could be more code surrounding this.

Related Topic