2

I am doing some test code right now. In my Apex code I have a method that try-catches a DMLException and afterwards does a general Exception catch.

In my test code I am successfully managing to test both(they come out as success), however salesforce doesn't acknowledge the test for the general exception.

Do you have any ideas? Thank you!

Here's my method code:

    public void createTimeSheet() {
        errorMsg = '';
        TimeSheet__c newTimeSheet = new TimeSheet__c(
            Date__c = date.valueOf(newTimeSheetDate),
            Status__c = 'New',
            Employee__c = [SELECT Id FROM Employee__c WHERE Name=:EmployeeName].Id
        );
        try {
            insert newTimeSheet;
        //catching the DML exceptions first
        } catch(DmlException e) {
            errorMsg = e.getDmlMessage(0);
            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.ERROR,errorMsg));
        //catching all other exceptions
        } catch(Exception e) {
            errorMsg = e.getMessage();
            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.ERROR,errorMsg));
        }
}

And here's my test method code:

public static testMethod void createTimeSheetNullPointerFail_test() {
        init();

        cont.EmployeeName = testEmployeeName;
        cont.tslist = testTsList;

        test.startTest();
            cont.createTimeSheet();
        test.stopTest();
        System.assert(cont.errorMsg.contains('System.NullPointerException: Attempt to de-reference a null object'), cont.errorMsg);
    }
3
  • 1
    How are you causing the null pointer exception to be thrown during your unit test execution within the try block?
    – Mark Pond
    Commented Feb 8, 2016 at 17:58
  • I'm not giving a value to the newTimeSheetDate variable in my test class. So when the test runs through the main method it returns a null pointer because of that.
    – Arthlete
    Commented Feb 8, 2016 at 18:21
  • 2
    That would not be NullPointerException, it would be Argument cannot be null. Instead of asserting false or true, temporarily assert null,cont.errorMsg and you will see the error it is returning
    – Eric
    Commented Feb 8, 2016 at 18:23

2 Answers 2

3

Exceptions have a type (e.g. "NullPointerException") and a message (e.g. "Argument cannot be null") and perhaps most usefully of all a stack trace (the line number and class name that the exception was thrown from and the calling line numbers and class names). If you are going to add error handling logic for random programming errors then I recommend that you capture all 3 pieces of information as otherwise you are making the process of finding and fixing the error harder than it needs to be.

See the Common Exception Methods that are available.

It is often be better to not add logic that tries to handle programming errors. For example, in a Visualforce controller class the default error handling works well and the stack trace detail can be obtained by turning on "Development Mode" for a User and reproducing the error using that User.

Running this using "Execute Anonymous":

try {
    Date.valueOf((String) null);
} catch (Exception e) {
    System.debug('>>> ' + e.getMessage());
}

confirms that the error message string will only contain "Argument cannot be null" (though FYI the exception thrown is of type "NullPointerException").

3
  • I'm a little leery of the advice "It is often be better to not add logic that tries to handle programming errors." I think without a little more context it could be mistaken. I also think it's somewhat bad practice to catch a generic Exception without knowing specifically which type you are guarding against (even if it's just copy-pasta). Otherwise worthy of a +1.
    – Adrian Larson
    Commented Feb 8, 2016 at 18:55
  • 1
    I think there's a common (mis)perception that exceptions always represent coding errors. It's been my observation that they represent data input errors or a failure to validate either the type of incoming data or catch data that is "out of bounds". This data later becomes problematic when being processed by our code. When we rely on the UI to validate, then data is later imported via bulk, that's when we esp encounter these problems.
    – crmprogdev
    Commented Feb 8, 2016 at 19:51
  • i kind of like having the general exception catcher include the stacktrace as I can at least hope the end user will send me a screen shot and I can diagnose without having to track the user down to reproduce the issue - especially with a global user base. I'm also with @crmprogdev here where data migrations and legacy unmigrated data sometimes comes back to haunt you - yes better procedures and rigorous SDLC and ISO 9001 type stuff could avoid this, but the all singing, all dancing sysad/dev sometimes doesn't have the bandwidth for this. But - I agree with all that is said above
    – cropredy
    Commented Feb 9, 2016 at 5:22
0

Sometimes difficulty writing test code can lead you to a better way of handling things in your actual code. Is the null pointer exception coming from the assignment of the employee ID? Why not do the query first and assign it to a list?

 public void createTimeSheet() {
    errorMsg = '';
    List<Employee__c> foundEmployees = [SELECT Id FROM Employee__c WHERE Name=:EmployeeName];
    if (foundEmployees.size() > 0) {
        TimeSheet__c newTimeSheet = new TimeSheet__c(
             Date__c = date.valueOf(newTimeSheetDate),
             Status__c = 'New',
            Employee__c = foundEmployees[0].Id
        );
    }
    else {
      // handle scenario here where the employee wasn't found, show error on page possibly
      // also consider adding else if scenario if more than 1 employee is found that matches the name
    }
    // TODO evaluate if try/catches are still needed
    try {
        insert newTimeSheet;
    //catching the DML exceptions first
    } catch(DmlException e) {
        errorMsg = e.getDmlMessage(0);
        ApexPages.addmessage(new ApexPages.message(ApexPages.severity.ERROR,errorMsg));
    //catching all other exceptions
    } catch(Exception e) {
        errorMsg = e.getMessage();
        ApexPages.addmessage(new ApexPages.message(ApexPages.severity.ERROR,errorMsg));
    }

}

You must log in to answer this question.

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