13

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)
  • I WANT the exception to be thrown. But the unit test seems to catch the DMLException while the Deploy doesn't. I'm trying to figure out if I can get the rest of that Failure Message. – Chris K Jan 24 '14 at 23:11
  • 4
    I'd say don't test it. Val. rules aren't code, they CAN change (or be disabled) on production without the need to rerun all tests. And if you do have an unit test for scenario like that you need to ask whether your user is allowed (Profile based? Role based? would it work for fellow developer sitting next to you)? Maybe it's a valid scenario that Sysadmins can't escalate. In which case you need for example System.runAs to impersonate the VP of Sales. – eyescream Jan 24 '14 at 23:11
  • @eyescream my comment got removed :(, prolly i was editing and hit the X mark. Even if chris uses system.runas I would say that there is still a good chance the class would fail if the VP profile does not have edit/read access to some fields until we see the complete code its safe to not test as u suggested salesforce.com/us/developer/docs/apexcode/Content/… – Rao Jan 24 '14 at 23:14
  • 1
    I think the code you posted it out of date, or possibly failed to save. The stack trace posted shows the DMLException thrown on line 29, which in the posted code is the closing brace of a catch block - not a place an exception would be thrown from. – ca_peterson Jan 25 '14 at 5:41
  • 1
    @ChrisKaminski Add your resolution as an answer, and accept it. The next person to have this issue may not read all these comments :) – Jason Clark Feb 6 '14 at 18:35
1

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.

  • I don't use RunAs because I'm testing the validation rule failure to fix code coverage - I NEED this rule to get triggered short of a total refactor. Why is this getting marked as a failure when I'm catching the exception in the SFDC-approved manner? Is this just impossible to do? – Chris K Jan 27 '14 at 23:09
1

It was recommended I answer this question: a complete rebuild of my code base from within SalesForce itself (not Force.com IDE) appears to have completely resolved this problem. I also resynced my local project with the Server after doing so (saving my changes beforehand, just in case).

I have no reliable explanation as to how this event came to pass, but a total recompilation made it go away.

0

This looks like a bug, if you're catching the exception in your unit test it shouldn't be flagging the test as a failure. If you haven't already please contact support so they can get this fixed.

  • Thank you for the response - but it appears to have been a compilation mismatch on my part. Some interaction between Force.com IDE and the SFDC dev console. :-/ – Chris K Feb 7 '14 at 19:54
0

Probably not going to help, but maybe try making all of your exceptions the standard Exception instead of DMLException. (I know one is already like that, but its worth a shot if this still isn't working.)

  • Thank you for the response - but it appears to have been a compilation mismatch on my part. Some interaction between Force.com IDE and the SFDC dev console. :-/ – Chris K Feb 7 '14 at 19:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.