1

I have a trigger on Opportunity which runs when the Opportunity is closed as Won.

The trigger checks if the Opportunity line item has a specific product(Id is hard coded in the code) and then does sequence of events.

I am trying to increase the test coverage for this class but the problem I am facing is I create a test product and simulate all the actions but the if block in trigger where Id is compared always evaluate to false as the test product Id does not match with the Id hard coded in the trigger. In this case how to increase the test coverage?

One option i see is to enable the seeAllData=TRUE on the test class and use the real product but I would like to know if there is any better option in this scenario?

EDIT:

Below is the code that I am trying to unit test:

trigger UpdateTRACKCaseDates on Case (after update) {

//This is to get the Record Type ID for the child Case.
Id childCaseRTId = Case.sObjectType.getDescribe().getRecordTypeInfosByName().get('Child Case').getRecordTypeId();

Set<Id> oppIds = new Set<Id>();

Map<String,Case> psCaseObjMap = new Map<String,Case>(); //This collection holds the oppID and the corresponding TEST_PRODUCT case Object.

for(Integer i =0; i< Trigger.size; i++){

    if(Trigger.isUpdate){

        Boolean condition = Trigger.new[i].IsClosed;
        condition = condition && (Trigger.new[i].Product__c == '01tdZZZZZZZZzyFguAAE'); // Id 01td0000000yFguAAE is for TEST_PRODUCT product
        condition = condition && (Trigger.old[i].Campaign_End_Date__c != Trigger.new[i].Campaign_End_Date__c);

        if(condition){

            Id oppId = Trigger.new[i].Opportunity__c;

            psCaseObjMap.put(String.valueOf(oppId),(Case)(Trigger.new[i]));

            oppIds.add(oppId);          

        }                   
    }               
}

List<Sobject> oppSObList = [SELECT Id, (SELECT CaseNumber,Description,Subject,Product__c FROM Cases__r WHERE Product__c = '01tdKKKKKKKKKyFgpAAE') FROM Opportunity WHERE Id IN :oppIds];

List<Case> ptCaseObjList = new List<Case>();

for(Sobject oppSobj: oppSObList){
    Case ptCaseObj = (Case)oppSobj.getSObjects('Cases__r')[0];

    ptCaseObj.Campaign_Start_Date__c = psCaseObjMap.get(String.valueOf(oppSobj.get('Id'))).Campaign_Start_Date__c; 

    ptCaseObj.Campaign_End_Date__c = psCaseObjMap.get(String.valueOf(oppSobj.get('Id'))).Campaign_End_Date__c; 
    ptCaseObjList.add(ptCaseObj);
}

upsert ptCaseObjList;

}

9
  • 1
    Another option is to not hardcode the id ..... is there a specific reason you have done this? Please note hardcoding id's is as far from best practice as SOQL statements in for loops. Commented Jul 17, 2015 at 23:06
  • Business gave the requirement that when this particular product is added to the opportunity then perform this action..How do I handle this situation? Should I create a custom field on the Product Object and control the execution based on that in the code? Pls suggest..I get these kind of requests from client very often.
    – javanoob
    Commented Jul 17, 2015 at 23:10
  • 1
    Generally you would do a select statement for the product by name or product code and then use the result for any further processing. If you want to provide some code snippets in your question I can help provide some better direction. Commented Jul 17, 2015 at 23:11
  • Have you considered use the Product's Name instead of product's Id? I assume that you won't have two products with the same name.
    – Joca
    Commented Jul 17, 2015 at 23:12
  • 1
    This kind of problem needs to be solved with either a custom setting or custom object used solely to specify configuration data - Ralph has the right answer.
    – cropredy
    Commented Jul 18, 2015 at 0:12

2 Answers 2

5

First some general tips

  • Put business logic for triggers in an apex class, and then reference this from the trigger
  • Don't hardcode ids

You have a couple options

1 - Test Hooks

For this to work you have to put your business logic in a separate class. Then you can add a "test hook", whereby your test can set the id of the product that triggers this action. Then in your test, you'll create a product, and set the test hook to the id of that product

2 - Drive Action from Configuration

Instead of hard coding an id, you can drive this behavior from a field on the product (i.e. Create_Campaing_Case__c). Then your test just needs to set that field to true to test the behavior.

You can also store the id in a custom setting, in which case your test would create a product and then put it's id in the custom setting.

0

Try this:

...
// Omitted first 8 lines
Map<Id, Case> newCases = new Map<Id, Case>([SELECT Product__r.Name FROM Case WHERE Id IN :Trigger.NEW]);
for(Integer i =0; i< Trigger.size; i++){
     if(Trigger.isUpdate){

        Boolean condition = Trigger.new[i].IsClosed;
        condition = condition &&(newCases.get(Trigger.new[i].Id).Product__r.Name == 'TEST_PRODUCT'); // Id 01td0000000yFguAAE is for TEST_PRODUCT product
        condition = condition && (Trigger.old[i].Campaign_End_Date__c != Trigger.new[i].Campaign_End_Date__c);
// The rest of your trigger code
...

and the product that you create for your test should be:

Product2 testProduct = new Product2(Name = 'TEST_PRODUCT');
insert testProduct;
Case testCase = new Case(Product__c = testProduct.Id);

You must log in to answer this question.

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