+ Start a Discussion

Test Coverage and Formula Fields

I'm having a hard time writing a test method for a custom object that has Formula Fields on them that are being used in the methods I am trying to cover.


When I debug the fields in the test method they are coming up as null, but, if I query the record it shows those fields as being updated correctly.


Where I run into a problem is when I have nested formula fields and then pass the final record I want tested to the method via a trigger.  The field that starts at the top level of the hierarchy hasn't made it all of the way to the final record.


Is there something I'm missing or do I need to query each and every object before associating it to the next in the hierarchy?  The final record doesn't have a direct reference to the fields in question but the class queries them based on a set criteria.


Any help would be appreciated.  Thanks!

Best Answer chosen by Admin (Salesforce Developers) 
Ankit AroraAnkit Arora

Am afraid but formula fields are calculated once the record is updated or inserted, so to get values in test class you need to insert or update your record before using the formula field value in test class...



Ankit Arora


All Answers

Ankit AroraAnkit Arora

Am afraid but formula fields are calculated once the record is updated or inserted, so to get values in test class you need to insert or update your record before using the formula field value in test class...



Ankit Arora


This was selected as the best answer

Even I am facing this problem, and would like to know if its solution is possible. Please let me know as any help on this is mucho appreciated.


After inserting a test record you need to query the database for it so formula fields are populated.


For example, in a test method I inserted an Account, Contact, Lead, and Opportunity (testOpp).  The Opportunity looks up to the other 3 objects and has formula fields that pull data from all 3.  


If I pass my testOpp variable straight to my controller (or a trigger) then my asserts against the formula fields will fail.  I have to query for the testOpp then pass that variable to my controller.  This will have the formulas populated:


Opportunity testOppAfterInsert = [SELECT Id, AccountId.Formula1, Lead__r.Formula2, Contact__r.Formula3 FROM Opportunity WHERE Id = :testOpp.Id]; 

Soumya Srivastava 1Soumya Srivastava 1

I am doing the same but still i am getting null values for the fields which is making the boolean flag false.

        WorkOrder relatedwo1 = new WorkOrder();       
            relatedwo1.AccountId =  a.Id;
            relatedwo1.AssignmentCounter__c = 5.00;
            relatedwo1.Previously_Assigned_Vendor__c= vendors[1].Id;   
            relatedwo1.Property__c = prop1.Id;
            relatedwo1.City = prop1.FAS_City__c;   
            relatedwo1.State = prop1.FAS_State__c;
            relatedwo1.Street = prop1.Address2__c;           
            relatedwo1.VOR__c = false;
            relatedwo1.Vendor__c = setting.Dummy_Vendor_Id__c;
            relatedwo1.Subject = 'test';        
            relatedwo1.WOStatus__c = 'Pending Vendor Acceptance';
            relatedwo1.Create_OA_Request__c = true;    
            relatedwo1.IsRecurringFlag__c = false;      
            relatedwo1.Agreed_Due_Date__c = system.Date.today();
            relatedwo1.PromisedCompDate__c = system.Date.today();        
            relatedwo1.SMARTvendor__c = setting.Dummy_Vendor_Id__c;     
            relatedwo1.Has_run_assignment_process__c = true;     
            relatedwo1.IncomingWOLineCount__c = 1;
            relatedwo1.Regional_Aggregator_Area__c = area.Id;
            relatedwo1.Zone_Member__c = rAreaMember.Id;  
        insert relatedwo1;

        Capability__c cap = new Capability__c();        
        cap.Active__c = true;
        cap.SLA__c = 3;
        cap.Crew_Effort__c = 3.00;
        cap.Name = 'test capability';        
        cap.CreatedDate= System.Datetime.Now();
        cap.FullService__c = true;
        cap.Skill_Category__c = 'Full Service';
        insert cap;     
        WorkOrderLineItem woli = new WorkOrderLineItem();        
            woli.Status = 'New';        
            woli.DueDate__c = system.date.Today().addDays(-10);       
            woli.workOrderId = relatedwo1.Id;
            woli.description = 'abcd';
            woli.Capability__c = cap.Id; 
            woli.Adjusted_Crew_Effort__c = 4.00;
        insert woli; 
        WorkOrder newWorkO = [select Id,LineItemCount,Do_Vendor_Assignment__c,SalesforceDateAssigned__c,IncomingWOLineCount__c,Has_run_assignment_process__c,WOStatus__c,Vendor__c from WorkOrder where Id=:relatedwo1.Id ];

You can see I have inserted and queried the same but still the values related to formula also are not coming like IncomingWOLineCount__c which is null.

Shital SonkusaleShital Sonkusale
I am also facing the same issue. Below is the thread for my issue

Brandon HurleyBrandon Hurley

The best answer is not really correct. Formula fields can be referenced in before insert triggers. They are actually calculated when they are called.

For example.

trigger AccountTrigger on Account (before insert){
	for (Account A : trigger.new) {

In this case, you are changing a value on a text field before the record is inserted based on how a formula field is evaluated (which can be based on other field values for that record). This may help with DML governor limits. However, when you try to debug in a test class, you run into issues. system.debug wont trigger the evaluation of the formula field, so you'll get a null value.

You can, however, insert a record in the test class that meets the criteria of the formula such that the formula outputs"value1", write an SOQL query WHERE account.text_field__c = "Value2",  then write a system.assert() and you'll find that there is a record that was updated per your requirements above.

TL;DR, it works, and formula fields can be referenced in before triggers.

Furthermore, in before update triggers, formula fields are evaluated based on the newest information possible. So if a field change in the before update trigger alters the output of the fomrula field, that is what is referenced in the before update trigger.