+ Start a Discussion
sfdc18sfdc18 

Trigger Test Class Error : Id not specified in an update call

Hi,

I am getting below error in test class for trigger on Case obj.

System.DmlException: Update failed. First exception on row 0; first error: MISSING_ARGUMENT, Id not specified in an update call: []

Trigger is working properly without any issues.
This Trigger adds Entitlement value on case based on related Service Contract.

Trigger :
trigger writeEntitlement on Case (after insert) {
    
   List<Case> caseInTrigger = [select id,Service_Contract__c,Case.EntitlementId from Case where id = :Trigger.NewMap.KeySet()];
   ID serviceContID;
   for(Case c : caseInTrigger)
   {
         serviceContID = c.Service_Contract__c;
   }
    
    ServiceContract sc = [select id,Entitlement__c from ServiceContract where id = :serviceContID];
    
    for(Case c : caseInTrigger)
    {
    
        c.EntitlementId = sc.Entitlement__c;
    }
    
    update caseInTrigger;
    
}

Test Class :
 

@isTest 
private class writeEntitlementTest {
    static testMethod void validatewriteEntitlement() {
    
     test.startTest(); 
    
       Case c = new Case();
        
       c.Service_Contract__c='81090000000D1lK';
       c.Origin='Web';
       c.Status='New';
       
       //insert c;
    
       ServiceContract sc = new ServiceContract();
       sc.id = '81090000000D1lK';
       sc.Entitlement__c = '55090000000D4pk';
   
    
  //     System.assertEquals(c.EntitlementId, sc.Entitlement__c);
       c.EntitlementId='55090000000D4pk';
       update c;
       
      test.stopTest();  

    }
}
Thanks & Regards,
Mayur
Best Answer chosen by sfdc18
Alex TennantAlex Tennant
In your test you are calling 'update' on your Case object 'c' before you've inserted it. To call update on an object it must already exist in the database.

Your test method has a lot of issues, you have hard coded Ids and are not creating your test data properly, in addition to this your test method also doesn't call 'System.assert()' at any point so it's not actually testing anything, it's only giving you code coverage.

Try something more like this (which isn't perfect, but is an improvement at least):

@isTest
private class writeEntitlementTest {
    static testMethod void validatewriteEntitlement() {
       Entitlement e = new Entitlement();
       // Complete any required fields here
       insert e;

       ServiceContract sc = new ServiceContract();
       sc.Entitlement__c = e.Id;
       // Complete any required fields here
       insert sc;

       Case c = new Case();
       c.Service_Contract__c = sc.Id;
       c.Origin='Web';
       c.Status='New';

       Test.startTest();
       insert c;
       Test.stopTest(); 
      
       System.assertEquals(sc.Entitlement__c, c.EntitlementId);
    }
}


All Answers

Alex TennantAlex Tennant
In your test you are calling 'update' on your Case object 'c' before you've inserted it. To call update on an object it must already exist in the database.

Your test method has a lot of issues, you have hard coded Ids and are not creating your test data properly, in addition to this your test method also doesn't call 'System.assert()' at any point so it's not actually testing anything, it's only giving you code coverage.

Try something more like this (which isn't perfect, but is an improvement at least):

@isTest
private class writeEntitlementTest {
    static testMethod void validatewriteEntitlement() {
       Entitlement e = new Entitlement();
       // Complete any required fields here
       insert e;

       ServiceContract sc = new ServiceContract();
       sc.Entitlement__c = e.Id;
       // Complete any required fields here
       insert sc;

       Case c = new Case();
       c.Service_Contract__c = sc.Id;
       c.Origin='Web';
       c.Status='New';

       Test.startTest();
       insert c;
       Test.stopTest(); 
      
       System.assertEquals(sc.Entitlement__c, c.EntitlementId);
    }
}


This was selected as the best answer
Alex TennantAlex Tennant
In addition to my comments about your test class your trigger is not properly bulkified and will not do what you want it to when you insert more than one Case at a time (it will apply the Entitlement Id of the last Case in the batch to all Cases in the batch). So you may want to look into fixing that.
PrasadVRPrasadVR

Why don't you do this in before trigges itself , what I understand is that . you want to update case EntitlementId with ServiceContract Entitlement . this you can do in before triggers itself .

try this 


trigger writeEntitlement on Case (before Insert,before Update) {
   
   Set<Id> serviceContIds = new Set<Id>();
   Map<Id,String> ServiceContractMap = new Map<Id,ServiceContract>();
  
   for(Case c : Trigger.new) {serviceContId.add(c.Service_Contract__c);}
     
   List<ServiceContract> sc = [select id,Entitlement__c from ServiceContract where id = :serviceContId];
   for(ServiceContract s :sc){ ServiceContractMap.put(s.Id,s.Entitlement__c); }
 
   for(Case c : caseInTrigger) {c.EntitlementId = ServiceContractMap.get(c.Service_Contract__c);}
     
}

Thanks 
Prasad VR