2

I am looking to deploy a Lightning component written by the amazing Jitendra Zaa. Unfortunately, there was no test class included with the component on his blog post. I have no idea where to begin in writing this one.

public class CircularProgressController {    

    /**
     * This class is used to return as JSON Object
     **/
    class WrapperJSON{
        public Integer total {get;set;}
        public Integer actual {get;set;}
        public Integer val {get;set;}
    }

    @AuraEnabled
    public static String computePercentage(String sObjectName, String recordId, String totalValueFieldName, String actualValueFieldName){
        Integer retVal = 0 ;
        String query = null;
        WrapperJSON retObj = new WrapperJSON();

        if(totalValueFieldName != null && totalValueFieldName.trim() != '' &&  actualValueFieldName != null && actualValueFieldName.trim() != '' ){
            query = 'SELECT '+totalValueFieldName+', '+actualValueFieldName+' FROM '+sObjectName+' WHERE Id =: recordId';
        }
        else if (actualValueFieldName != null && actualValueFieldName.trim() != '' ) {
            query = 'SELECT '+actualValueFieldName+' FROM '+sObjectName+' WHERE Id =: recordId';
        }

        if(query != null){
            try{
                List<SOBject> lstObj = Database.query(query);
                if(lstObj.size() > 0){
                    Decimal totalVal = 0;
                    Decimal actualVal = 0; 

                    if(totalValueFieldName != null && totalValueFieldName.trim() != ''){ 
                        totalVal = Decimal.valueOf(String.valueOf(lstObj[0].get(totalValueFieldName)));
                        retObj.total = Integer.valueOf(totalVal) ; 
                    } 
                    actualVal = Decimal.valueOf(String.valueOf(lstObj[0].get(actualValueFieldName)));                     
                    //Means only 1 API Name was supplied and field type is percentage
                    if(totalVal == 0){
                        retObj.val = Integer.valueOf(actualVal) ; 
                        retObj.actual = Integer.valueOf(actualVal) ;  
                    }else if (actualVal > 0){
                        retObj.val = Integer.valueOf( ( actualVal / totalVal ) * 100 );   
                        retObj.actual = Integer.valueOf(actualVal) ;  
                    } 
                }
            }catch(Exception e){}

        }         
        return JSON.serialize(retObj) ;        
    }
}

Where should I begin in testing this controller?

**EDIT: I realized thanks to given advice that I was overthinking most of this. I have put together a basic test class as follows. It's hard to test actual values for 99% of the use cases in this class because many are derived from formulas and are time specific values. Therefore I have opted to test against null. This is what I have so far.

    @IsTest
public class circularProgressControllerTest {

private static testMethod void runTest()
{
    Account acc = new Account(Name = 'Account Test', Type = 'Customer');
    insert acc;
    Case a = new Case(Subject = 'Account Tester', Status='New', Origin='Email', AccountId = [select id from Account where id =:acc.Id][0]);
    insert a;

     a = [select id, Status from Case where id =:a.Id][0];
     a.Status = 'Open';
        update a;
     a = [select id, First_Response_Time_Minutes_hidden__c, SLA_HI__c from Case where id =:a.Id][0];

    Set<String> JsonString = CircularProgressController.computePercentage(Case, a.Id, a.SLA_HI__c, a.First_Response_Time_Minutes_hidden__c);

    Map<String, Object> meta = (Map<String, Object>) JSON.deserializeUntyped(JsonString);
    List<Map<String, String>> myMaps = (List<Map<String, String>>) meta.get('results');

   Test.startTest();

   System.assertNotEquals(null, myMaps.Val);

   Test.stopTest();


    }

}

It's important that I run the Case update section, as the only use case of this component requires it to calculate SLA times in a 'prettier' fashion. The issue I am running into now is assigning the sObject of Case - 'Variable does not exist: Case'.

5
  • 5
    Trailhead might be a good place to begin if you haven't worked through the module on Unit Tests. :) Once you get through that, you should at least know how to begin.
    – Adrian Larson
    May 10, 2017 at 20:18
  • You're trying to do computePercentage(Case, a.Id, ...) where you need to do computePercentage(a, a.Id, ...).
    – Adrian Larson
    May 11, 2017 at 22:01
  • @AdrianLarson I switched the line to String JsonString = CircularProgressController.computePercentage(a, a.Id, a.SLA_HI__c, a.First_Response_Time_Minutes_hidden__c); and received: Method does not exist or incorrect signature: CircularProgressController.computePercentage(Case, Id, Decimal, Decimal) Is this because they are both Number formula fields? (SLA_HI and First Response)
    – Marc Swan
    May 11, 2017 at 23:07
  • If I pass an initiazation, as CircularProgressController.computePercentage JsonString = new CircularProgressController.computepercentage(a, a.Id, a.SLA_HI__c, a.First_Response_Time_Minutes_hidden__c); I receive Invalid type: CircularProgressController.computepercentage (Line: 15, Column: 67)
    – Marc Swan
    May 11, 2017 at 23:19
  • Testing for a non-null is a useless test. It's just asserting that you're getting a result, but you're not checking that the result makes any sense. If in the future someone changes the class and inadvertently changes the computations, your tests will not tell you what's broken. I would give more thought about this and test a few conditions. We're talking about basic arithmetics and calculating percentages here... it shouldn't be too hard.
    – mkorman
    May 12, 2017 at 10:43

1 Answer 1

2

Well, the class you posted only has one method, so it looks like the right way to start is to test that single method :)

Of course, you need to understand what it does before testing.

It looks like the method does the following:

  • query the database for a certain object of a sObjectName type, with a given recordId, retrieving the totalValueFieldName and the actualValueFieldName
  • Does some calucations
  • Returns an instance of a WrapperJSON with the result.

There seems to be different behaviour when the totalVal is zero and when it's non-zero.

I would create 2 methods that:

  • Instantiate and insert an SObject, specifying the total value and the actual value. One method should set totalVal to 0 and another to non-zero.
  • Call the method under test and receive a WrapperJSON result
  • Deserialize the WrapperJSON
  • Verify that the de-serialized result is what you expected

If you're not comfortable with the constructs of creating a test class and test methods, then I would check the Trailhead module recommended by Adrian Larson above.

2
  • Your advice has given me a solid roadmap. I think I was letting myself get tripped up over the mass of calculation lines, and forgetting that I really just need to test the method results and provide proper input for the method. I am really just now unsure of how to initiate the Class properly, and how to retrieve the results. Would I use something like this? CircularProgressController.ComputePercentage(Case, c.Id, c.SLA_HI__c, First_Response_Time_Minutes_hidden__c);// Invocable method test.
    – Marc Swan
    May 11, 2017 at 18:15
  • The signature of the method is: String computePercentage(String sObjectName, String recordId, String totalValueFieldName, String actualValueFieldName). You need to pass 2 strings with the names of the fields: SLA_HI__c, First_Response_Time_Minutes_hidden__c. You need to review your Apex basics: how to pass arguments to methods, etc.
    – mkorman
    May 12, 2017 at 10:42

You must log in to answer this question.

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