FIELD_CUSTOM_VALIDATION_EXCEPTION during Unit Test

I have a validation rule, such that setting a Case escalation status to “approved” can only be done via particular users and/or emails via the automated email parser. I have a Unit Test that accounts for this case, like so:

@isTest
private class UnitTests_CaseEscalationDecision {

    static testMethod void testEscalationApprovers() { 
        Map<String, User> uMap = Case_DataFactory.getEscalationApprovers(); 
        System.assert(uMap != null, 'Escalation Approver list is null'); 
    }

    static testMethod void CaseEscalationDecision_Approved() {
        test.startTest();

        // Unit Test for Case Esclation Trigger
        // JC 4/29/13

        // TO DO: implement unit test

        // Create a Case
        Case cs = new case(Subject = 'Unit Test Escalation Request');
        cs.Status = 'New';
        cs.RecordTypeId = '01240000000DqfI';  // Case type == Support
        insert cs;

        // Escalate the Case 
        cs.Escalation_Status__c = 'Approved';
        cs.Escalation_Reason__c = 'Customer Request';
        cs.Escalation_Details__c = 'This is a unit test for Escalation - Please ignore';

        try { 
            update cs;
            System.assert(false, 'This should never be reached!  No valid approver.');
        } catch ( Exception ex) {
            System.assert(true, 'This should evaluate to true because there is no valid approver.');
            System.debug('CaseEscalationDecision_Approved Exception caught!');
            System.debug(ex.getMessage() ); 
            System.debug(ex.getStackTraceString() );
        }

        test.stopTest();    

    }

    static testMethod void CaseEscalationDecision_RequestedApproved() {
        test.startTest();

        // Unit Test for Case Esclation Trigger
        // JC 4/29/13

        // TO DO: implement unit test

        // Create a Case
        Case cs = new case(Subject = 'Unit Test Escalation Request');
        cs.Status = 'New';
        cs.RecordTypeId = '01240000000DqfI';  // Case type == Support
        insert cs;

        // Escalate the Case 
        cs.Escalation_Status__c = 'Requested';
        cs.Escalation_Reason__c = 'Customer Request';
        cs.Escalation_Details__c = 'This is a unit test for Escalation - Please ignore';
        update cs;

        try { 
            cs.Escalation_Status__c = 'Approved'; 
            update cs;
            System.assert(false, 'This should never be reached!  No valid approver.');
        } catch (DMLException ex) {
            System.assert(true, 'This should evaluate to true because there is no valid approver.');
        }

        test.stopTest();    

    }

}

The exception is thrown as expected, and caught (I swallow the DMLException on purpose) when I run the unit test from the Force.com IDE. Even with this exception handler in place, the Test is marked a failure in the Developer Console, and so when I go to deploy, the test fails:

Failure Message: “System.DmlException: Update failed. First exception on row 0 with id 5004000000XCpUnAAL; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, Escalation status can only be changed to Approved or Denied by the EVP of Sales or Support Management.: [Escalation_Status__c]”, Failure Stack Trace: “Class.UnitTests_CaseEsca…

I know all Tests have to pass in order to deploy, and this is one of a small handful I can’t seem to make pass.

Any thoughts?

EDIT – Debug Log Entry

18:51:46.723 (7723562000)|CODE_UNIT_FINISHED|Validation:Case:500M0000003lwNw
18:51:46.724 (7724920000)|DML_END|[29]
18:51:46.724 (7724985000)|VF_PAGE_MESSAGE|Escalation status can only be changed to Approved or Denied by the EVP of Sales or Support Management.
18:51:46.725 (7725075000)|EXCEPTION_THROWN|[29]|System.DmlException: Update failed. First exception on row 0 with id 500M0000003lwNwIAI; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, Escalation status can only be changed to Approved or Denied by the EVP of Sales or Support Management.: [Escalation_Status__c]
18:51:46.726 (7726147000)|USER_DEBUG|[33]|DEBUG|CaseEscalationDecision_Approved Exception caught!
18:51:46.726 (7726189000)|USER_DEBUG|[34]|DEBUG|Update failed. First exception on row 0 with id 500M0000003lwNwIAI; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, Escalation status can only be changed to Approved or Denied by the EVP of Sales or Support Management.: [Escalation_Status__c]
18:51:46.726 (7726252000)|USER_DEBUG|[35]|DEBUG|Class.UnitTests_CaseEscalationDecision.CaseEscalationDecision_Approved: line 29, column 1
18:51:46.727 (7727033000)|CODE_UNIT_FINISHED|UnitTests_CaseEscalationDecision.CaseEscalationDecision_Approved

Developer Console Test output:
Developer Console Test output:

In Force.com IDE and Developer Console I am executing as user “Chris Kaminski.”
Validation Rule Criteria:

if(and(ischanged(Escalation_Status__c),
OR(ISPICKVAL( Escalation_Status__c ,"Approved"), 
ISPICKVAL(Escalation_Status__c,"Denied")), 
NOT((OR( $User.FirstName ="Automated",CONTAINS($UserRole.Name,"Manager of Support"),
CONTAINS($UserRole.Name,"EVP of Sales"),CONTAINS($UserRole.Name,
"EVP SaaS Engineering & Operations"),CONTAINS($UserRole.Name,"CEO/CFO"))))),
true, false)

Answer

Not a complete fix and probably not best practice, but I’ve had similar issues where my tests hit the validation rules and therefore fail.

If you absolutely need to get it deployed and don’t have time to write your test with runAs(), you could deactivate the validation rule on both source and target environments, make your deployment, then reactivate the validation rules. This would allow the Tests to pass as there are no validation rules to prevent them from passing.

Again, probably not best practice, but it lets you make your deployment.

Attribution
Source : Link , Question Author : Chris K , Answer Author : zainogj

Leave a Comment