function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
SkeeterSkeeter 

Trigger causing inbound change set issues

I recently deployed a trigger to require rejection comments on an approval process along with the test class.  I didn't have any issues in sandbox and received 100% code coverage, but after deploying succesfully to production inbound change sets will sometimes fail and generate the trigger error.  Any help is greatly appreciated.  I'm not sure what I'm missing.
 
System.DmlException: Process failed. First exception on row 0; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, Select the back button and provide a rejection reason comment.: [] 
Stack Trace: Class.RequireRejectionCommentTestClass.testRejectionWithComment: line 65, column 1
 
trigger RequireRejectionComment on License_Request__c (before update) {
       Map<Id, License_Request__c> rejectedRequests = new Map<Id, License_Request__c>{};
    
      for(License_Request__c lic: trigger.new)
      {

        License_Request__c oldLic = System.Trigger.oldMap.get(lic.Id);
    
        if (oldLic.Approval_Status__c != 'Rejected' 
         && lic.Approval_Status__c == 'Rejected')
        { 
          rejectedRequests.put(lic.Id, lic);  
        }
      }
       
      if (!rejectedRequests.isEmpty())  
      {

        
        List<Id> processInstanceIds = new List<Id>{};
        
        for (License_Request__c lics : [SELECT (SELECT ID
                                                  FROM ProcessInstances
                                                  ORDER BY CreatedDate DESC
                                                  LIMIT 1)
                                          FROM License_Request__c
                                          WHERE ID IN :rejectedRequests.keySet()])
        {
            processInstanceIds.add(lics.ProcessInstances[0].Id);
        }
          
        // Now that we have the most recent process instances, we can check
        // the most recent process steps for comments.  
        
        for (ProcessInstance pi : [SELECT TargetObjectId,
                                       (SELECT Id, StepStatus, Comments 
                                        FROM Steps
                                        ORDER BY CreatedDate DESC
                                        LIMIT 1 )
                                   FROM ProcessInstance
                                   WHERE Id IN :processInstanceIds
                                   ORDER BY CreatedDate DESC])   
        {                   
          if ((pi.Steps[0].Comments == null || 
               pi.Steps[0].Comments.trim().length() == 0))
          {
            rejectedRequests.get(pi.TargetObjectId).addError(
              'Select the back button and provide a rejection reason comment.');
          }
        }  
      } 

    }

 
Geoffrey J FlynnGeoffrey J Flynn
Are you pushing all the test classes at the same time?  Is it 100% code coverage in both Production and Sandbox?
mjohnson-TICmjohnson-TIC
Can you include code from your test class RequireRejectionCommentTestClass?
SkeeterSkeeter
Yes,  I have gotten 100 % code coverage in production and sandbox.  Here is my test class:
 
@IsTest 
  
    public class RequireRejectionCommentTestClass {
    
          private static testmethod void testRejectionWithComment()
        {
           
              User emp = [SELECT Id From User WHERE Alias = 'Admin'] ; 
  
            //Create records for lookup fields on parent record
                    
            License_Type__c typ = new License_Type__c(Name='Testing1');
            typ.Unit_Price__c = Decimal.valueOf('1.00');
            typ.Period__c = 'Monthly';       
            insert typ;
            
            Cost_Center__c cost = new Cost_Center__c(Name='Cost Center Test1');
            cost.Default_GL__c = '123456';
              cost.Finance_Owner__c = emp.Id;
            insert cost;
                
            License_Request__c lic = new License_Request__c();
            lic.Name = 'Salesforce Test1';
            lic.Quantity__c = Decimal.valueOf('1.0');
            lic.License_Type__c = typ.Id;
            lic.Cost_Center__c = cost.Id;
              lic.Business_Owner__c = emp.Id;
              lic.Status__c = 'Needs Approval';
                //lic.Approval_Status__c = 'Rejected';
                lic.OwnerId = emp.Id;
            insert lic;
            
              Id licId = generateAndSubmitObject();
              
            // Reject the submitted request, providing a comment.
            Approval.ProcessWorkitemRequest testRej = new Approval.ProcessWorkitemRequest();
            testRej.setComments('Rejecting request with a comment.');
            testRej.setAction  ('Reject');
            testRej.setWorkItemId(licId);
        
            Test.startTest();        
            
              // Process the rejection
            Approval.ProcessResult testRejResult =  Approval.process(testRej);
            
              Test.stopTest();
            
            // Verify the rejection results
            System.assert(testRejResult.isSuccess(), 'Rejections that include comments should be permitted');
            System.assertEquals('Rejected', testRejResult.getInstanceStatus(), 
              'Rejections that include comments should be successful and instance status should be Rejected');
        }
                  
              
        private static testmethod void testRejectionWithoutComment()
        {
             //Create Parent Object
            User emp1 = [SELECT Id From User WHERE Alias = 'Admin'] ; 
              
            License_Type__c typ2 = new License_Type__c(Name='Testing2');
            typ2.Unit_Price__c = Decimal.valueOf('1.00');
            typ2.Period__c = 'Monthly';
            insert typ2;
            
            Cost_Center__c cost2 = new Cost_Center__c(Name='Cost Center Test2');
            cost2.Default_GL__c = '666666';
              cost2.Finance_Owner__c = emp1.Id;
            insert cost2;
                
            License_Request__c lic2 = new License_Request__c();
            lic2.Name = 'Salesforce Test2';
            lic2.Quantity__c = Decimal.valueOf('1.0');
            lic2.License_Type__c = typ2.Id;
            lic2.Cost_Center__c = cost2.Id;
              lic2.Business_Owner__c = emp1.Id;
              lic2.Status__c = 'Needs Approval';
              lic2.Approval_Status__c = 'Rejected';
            insert lic2;
            
              Id lic2Id = generateAndSubmitObject();
              
            // Reject the submitted request, without providing a comment.
            Approval.ProcessWorkitemRequest testRej = new Approval.ProcessWorkitemRequest();
            testRej.setComments('');
            testRej.setAction  ('Reject');      
            testRej.setWorkitemId(lic2Id);
        
           Test.startTest();        
              
           // Attempt to process the rejection;
                
                try
                {
                    Approval.ProcessResult testRejResult =  Approval.process(testRej);
                    system.assert(false, 'A rejection with no comment should cause an exception');
                }
                catch(DMLException e)
                {
                    system.assertEquals('Select the back button and provide a rejection reason comment.', 
                                        e.getDmlMessage(0), 
                      'error message should be: Select the back button and provide a rejection reason comment.'); 
                }
            Test.stopTest();
        }
        
    
        private static testmethod void testApprovalWithoutComment()
              
        {
         //Create Parent Object
            
              User emp3 = [SELECT Id From User WHERE Alias = 'Admin'] ; 
              
            License_Type__c typ3 = new License_Type__c(Name='Testing');
            typ3.Unit_Price__c = Decimal.valueOf('1.00');
            typ3.Period__c = 'Monthly';          
            insert typ3;
            
            Cost_Center__c cost3 = new Cost_Center__c(Name='Cost Center Test3');
            cost3.Default_GL__c = '111111';
              cost3.Finance_Owner__c = emp3.Id;
            insert cost3;
                
            License_Request__c lic3 = new License_Request__c();
            lic3.Name = 'Salesforce Test3';
            lic3.Quantity__c = Decimal.valueOf('1.0');
            lic3.License_Type__c = typ3.Id;
            lic3.Cost_Center__c = cost3.Id;
              lic3.Business_Owner__c = emp3.Id;
              lic3.Status__c = 'Needs Approval';
              lic3.Approval_Status__c = 'Approved';
            insert lic3;
            
              Id lic3Id = generateAndSubmitObject();
              
            // Approve the submitted request, without providing a comment.
            Approval.ProcessWorkitemRequest testApp = new Approval.ProcessWorkitemRequest();
            testApp.setComments ('');
            testApp.setAction   ('Approve');
              testApp.setNextApproverIds (new Id[] {emp3.Id});
              testApp.setWorkitemId(lic3Id);
        
            Test.startTest();  
                                    
              // Process the approval
            Approval.ProcessResult testAppResult =  Approval.process(testApp);
            
              Test.stopTest();
            
            // Verify the approval results
            System.assert(testAppResult.isSuccess(), 
                         'Approvals that do not include comments should still be permitted');
            System.assertEquals('Pending', testAppResult.getInstanceStatus(), 
               'All approvals should be successful and result in an instance status of Approved');
        }
        
  
  
        
  
      private static Id generateAndSubmitObject()
              
        {
             //Create Parent Object
            User emplr = [SELECT Id From User WHERE Alias = 'Admin'] ; 
              
            License_Type__c typ1 = new License_Type__c(Name='Testing4');
            typ1.Unit_Price__c = Decimal.valueOf('1.00');
            typ1.Period__c = 'Monthly';          
            insert typ1;
            
            Cost_Center__c cost1 = new Cost_Center__c(Name='Cost Center Test4');
            cost1.Default_GL__c = '222222';
              cost1.Finance_Owner__c = emplr.Id;
            insert cost1;
                
            License_Request__c testlr = new License_Request__c();
            testlr.Name = 'Salesforce Test4';
            testlr.Quantity__c = Decimal.valueOf('1.0');
            testlr.License_Type__c = typ1.Id;
            testlr.Cost_Center__c = cost1.Id;
              testlr.Business_Owner__c = emplr.Id;
              testlr.Status__c = 'Needs Approval';
            insert testlr;
            
            Approval.ProcessSubmitRequest testReq = new Approval.ProcessSubmitRequest();
            testReq.setObjectId(testlr.Id);
            Approval.ProcessResult reqResult = Approval.process(testReq);
            
            System.assert(reqResult.isSuccess(),'Unable to submit new License Request record for approval');
            
            return reqResult.getNewWorkitemIds()[0];
        }          
   
       
      }

 
mjohnson-TICmjohnson-TIC
You have a validation rule in production that is not in sandbox preventing either License_Type__c or Cost_Center__c record to be inserted without a "rejection reason comment" (as you errored in the validation). Either add this rejection reason comment to your test class record before insert/update, remove the production validation or write an exception to your production validation for !$User.Alias != 'DeploymentUserAlias'.