Send out email when Apex Queueable fails and test it





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ margin-bottom:0;
}







4















This question definitely is a duplicate of many questions here, but after reading most of them I am still somewhat clueless.



Question 1: why I can't just catch exceptions in the execute and send an email out? Would a) Batch help, or b) checking or c) writing a custom Error object?



public class MyQueue implements Queueable, Database.AllowsCallouts {

public void execute(QueueableContext context) {
try {
Integer invalid = 100 / 0;
}
catch(Exception ex) {
sendEmail(ex);
}
}
}


Question 2: Can I test it like this?



@IsTest
private class MyQueue_Test {

@IsTest
private static void sendsEmailOnError() {

// Exercise
Test.startTest();
System.enqueueJob(new MyQueue());
Test.stopTest();

// Verify
System.assertEquals(1, Limits. getEmailInvocations());
}
}









share|improve this question


















  • 2





    Can you elaborate "can not" please? Is that because it does not work (and what is an error), or is that because it is written somewhere not to do it or any other reason?

    – kurunve
    Apr 2 at 14:10











  • Sure, no email is "sent", not even an exception is thrown. In my logs I see a Script-Thrown Exception which is not caught by the catch().

    – Robert Sösemann
    Apr 2 at 14:23


















4















This question definitely is a duplicate of many questions here, but after reading most of them I am still somewhat clueless.



Question 1: why I can't just catch exceptions in the execute and send an email out? Would a) Batch help, or b) checking or c) writing a custom Error object?



public class MyQueue implements Queueable, Database.AllowsCallouts {

public void execute(QueueableContext context) {
try {
Integer invalid = 100 / 0;
}
catch(Exception ex) {
sendEmail(ex);
}
}
}


Question 2: Can I test it like this?



@IsTest
private class MyQueue_Test {

@IsTest
private static void sendsEmailOnError() {

// Exercise
Test.startTest();
System.enqueueJob(new MyQueue());
Test.stopTest();

// Verify
System.assertEquals(1, Limits. getEmailInvocations());
}
}









share|improve this question


















  • 2





    Can you elaborate "can not" please? Is that because it does not work (and what is an error), or is that because it is written somewhere not to do it or any other reason?

    – kurunve
    Apr 2 at 14:10











  • Sure, no email is "sent", not even an exception is thrown. In my logs I see a Script-Thrown Exception which is not caught by the catch().

    – Robert Sösemann
    Apr 2 at 14:23














4












4








4








This question definitely is a duplicate of many questions here, but after reading most of them I am still somewhat clueless.



Question 1: why I can't just catch exceptions in the execute and send an email out? Would a) Batch help, or b) checking or c) writing a custom Error object?



public class MyQueue implements Queueable, Database.AllowsCallouts {

public void execute(QueueableContext context) {
try {
Integer invalid = 100 / 0;
}
catch(Exception ex) {
sendEmail(ex);
}
}
}


Question 2: Can I test it like this?



@IsTest
private class MyQueue_Test {

@IsTest
private static void sendsEmailOnError() {

// Exercise
Test.startTest();
System.enqueueJob(new MyQueue());
Test.stopTest();

// Verify
System.assertEquals(1, Limits. getEmailInvocations());
}
}









share|improve this question














This question definitely is a duplicate of many questions here, but after reading most of them I am still somewhat clueless.



Question 1: why I can't just catch exceptions in the execute and send an email out? Would a) Batch help, or b) checking or c) writing a custom Error object?



public class MyQueue implements Queueable, Database.AllowsCallouts {

public void execute(QueueableContext context) {
try {
Integer invalid = 100 / 0;
}
catch(Exception ex) {
sendEmail(ex);
}
}
}


Question 2: Can I test it like this?



@IsTest
private class MyQueue_Test {

@IsTest
private static void sendsEmailOnError() {

// Exercise
Test.startTest();
System.enqueueJob(new MyQueue());
Test.stopTest();

// Verify
System.assertEquals(1, Limits. getEmailInvocations());
}
}






apex unit-test asynchronous queueable-interface






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Apr 2 at 14:07









Robert SösemannRobert Sösemann

13.2k1178226




13.2k1178226








  • 2





    Can you elaborate "can not" please? Is that because it does not work (and what is an error), or is that because it is written somewhere not to do it or any other reason?

    – kurunve
    Apr 2 at 14:10











  • Sure, no email is "sent", not even an exception is thrown. In my logs I see a Script-Thrown Exception which is not caught by the catch().

    – Robert Sösemann
    Apr 2 at 14:23














  • 2





    Can you elaborate "can not" please? Is that because it does not work (and what is an error), or is that because it is written somewhere not to do it or any other reason?

    – kurunve
    Apr 2 at 14:10











  • Sure, no email is "sent", not even an exception is thrown. In my logs I see a Script-Thrown Exception which is not caught by the catch().

    – Robert Sösemann
    Apr 2 at 14:23








2




2





Can you elaborate "can not" please? Is that because it does not work (and what is an error), or is that because it is written somewhere not to do it or any other reason?

– kurunve
Apr 2 at 14:10





Can you elaborate "can not" please? Is that because it does not work (and what is an error), or is that because it is written somewhere not to do it or any other reason?

– kurunve
Apr 2 at 14:10













Sure, no email is "sent", not even an exception is thrown. In my logs I see a Script-Thrown Exception which is not caught by the catch().

– Robert Sösemann
Apr 2 at 14:23





Sure, no email is "sent", not even an exception is thrown. In my logs I see a Script-Thrown Exception which is not caught by the catch().

– Robert Sösemann
Apr 2 at 14:23










2 Answers
2






active

oldest

votes


















5














The problem is that Test.stopTest executes the asynchronous code, then resets the governor limits back to the state it was in immediately before Test.startTest is called. If you really wanted to verify the output, you'd need a static method to check:



public class MyQueue implements Queueable, Database.AllowsCallouts {
@TestVisible static Boolean emailSent = false;
public void execute(QueueableContext context) {
try {
Integer invalid = 100 / 0;
}
catch(Exception ex) {
sendEmail(ex);
emailSent = true;
}
}
}


And from there, test it in your unit test:



@IsTest
private class MyQueue_Test {

@IsTest
private static void sendsEmailOnError() {

// Exercise
Test.startTest();
System.enqueueJob(new MyQueue());
Test.stopTest();

// Verify
System.assert(MyQueue.emailSent);
}
}


This is one of those relatively rare conditions where the easiest way to perform a task is to inject test code to the actual code. You should do this minimally, of course, but as often as necessary.



Alternatively, a more idiomatic way to do this would be to use the Stub API. The idea here is that you'd mock out sendEmail by overriding it in the unit test. This is a bit complicated to use in practice, especially since you only need to add two lines of code.






share|improve this answer
























  • Should I use Database Savepoints and rollbacks in the catch or does Apex care about this? I mean if I do some DML in the try...

    – Robert Sösemann
    Apr 2 at 21:46






  • 1





    @RobertSösemann for testing, it doesn't matter. For production code, if you perform multiple DML and do not roll back, you may leave your data in an inconsistent state. If you're at all concerned about this possibility, definitely roll back. This is on a case by case situation, though. You'll need to analyze each case separately, and determine if partial success should be allowed.

    – sfdcfox
    Apr 2 at 22:25



















3














I usually take the route of storing results in a log object as opposed to email.



If you want, you can add a trigger to the log object to send out an email. You can enable activity tracking for the emails as well which would allow you to query for the existence of an activity as opposed to checking the governor limits.



The benefits being:




  • logs are more permanent

  • logs are less likely to get lost in email

  • logs are not user specific meaning if there is an issue and the email recipient is out of office, the log can be viewed and the issue can be resolved

  • you can report on logs/activities but not email






share|improve this answer


























    Your Answer








    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "459"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsalesforce.stackexchange.com%2fquestions%2f256225%2fsend-out-email-when-apex-queueable-fails-and-test-it%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    5














    The problem is that Test.stopTest executes the asynchronous code, then resets the governor limits back to the state it was in immediately before Test.startTest is called. If you really wanted to verify the output, you'd need a static method to check:



    public class MyQueue implements Queueable, Database.AllowsCallouts {
    @TestVisible static Boolean emailSent = false;
    public void execute(QueueableContext context) {
    try {
    Integer invalid = 100 / 0;
    }
    catch(Exception ex) {
    sendEmail(ex);
    emailSent = true;
    }
    }
    }


    And from there, test it in your unit test:



    @IsTest
    private class MyQueue_Test {

    @IsTest
    private static void sendsEmailOnError() {

    // Exercise
    Test.startTest();
    System.enqueueJob(new MyQueue());
    Test.stopTest();

    // Verify
    System.assert(MyQueue.emailSent);
    }
    }


    This is one of those relatively rare conditions where the easiest way to perform a task is to inject test code to the actual code. You should do this minimally, of course, but as often as necessary.



    Alternatively, a more idiomatic way to do this would be to use the Stub API. The idea here is that you'd mock out sendEmail by overriding it in the unit test. This is a bit complicated to use in practice, especially since you only need to add two lines of code.






    share|improve this answer
























    • Should I use Database Savepoints and rollbacks in the catch or does Apex care about this? I mean if I do some DML in the try...

      – Robert Sösemann
      Apr 2 at 21:46






    • 1





      @RobertSösemann for testing, it doesn't matter. For production code, if you perform multiple DML and do not roll back, you may leave your data in an inconsistent state. If you're at all concerned about this possibility, definitely roll back. This is on a case by case situation, though. You'll need to analyze each case separately, and determine if partial success should be allowed.

      – sfdcfox
      Apr 2 at 22:25
















    5














    The problem is that Test.stopTest executes the asynchronous code, then resets the governor limits back to the state it was in immediately before Test.startTest is called. If you really wanted to verify the output, you'd need a static method to check:



    public class MyQueue implements Queueable, Database.AllowsCallouts {
    @TestVisible static Boolean emailSent = false;
    public void execute(QueueableContext context) {
    try {
    Integer invalid = 100 / 0;
    }
    catch(Exception ex) {
    sendEmail(ex);
    emailSent = true;
    }
    }
    }


    And from there, test it in your unit test:



    @IsTest
    private class MyQueue_Test {

    @IsTest
    private static void sendsEmailOnError() {

    // Exercise
    Test.startTest();
    System.enqueueJob(new MyQueue());
    Test.stopTest();

    // Verify
    System.assert(MyQueue.emailSent);
    }
    }


    This is one of those relatively rare conditions where the easiest way to perform a task is to inject test code to the actual code. You should do this minimally, of course, but as often as necessary.



    Alternatively, a more idiomatic way to do this would be to use the Stub API. The idea here is that you'd mock out sendEmail by overriding it in the unit test. This is a bit complicated to use in practice, especially since you only need to add two lines of code.






    share|improve this answer
























    • Should I use Database Savepoints and rollbacks in the catch or does Apex care about this? I mean if I do some DML in the try...

      – Robert Sösemann
      Apr 2 at 21:46






    • 1





      @RobertSösemann for testing, it doesn't matter. For production code, if you perform multiple DML and do not roll back, you may leave your data in an inconsistent state. If you're at all concerned about this possibility, definitely roll back. This is on a case by case situation, though. You'll need to analyze each case separately, and determine if partial success should be allowed.

      – sfdcfox
      Apr 2 at 22:25














    5












    5








    5







    The problem is that Test.stopTest executes the asynchronous code, then resets the governor limits back to the state it was in immediately before Test.startTest is called. If you really wanted to verify the output, you'd need a static method to check:



    public class MyQueue implements Queueable, Database.AllowsCallouts {
    @TestVisible static Boolean emailSent = false;
    public void execute(QueueableContext context) {
    try {
    Integer invalid = 100 / 0;
    }
    catch(Exception ex) {
    sendEmail(ex);
    emailSent = true;
    }
    }
    }


    And from there, test it in your unit test:



    @IsTest
    private class MyQueue_Test {

    @IsTest
    private static void sendsEmailOnError() {

    // Exercise
    Test.startTest();
    System.enqueueJob(new MyQueue());
    Test.stopTest();

    // Verify
    System.assert(MyQueue.emailSent);
    }
    }


    This is one of those relatively rare conditions where the easiest way to perform a task is to inject test code to the actual code. You should do this minimally, of course, but as often as necessary.



    Alternatively, a more idiomatic way to do this would be to use the Stub API. The idea here is that you'd mock out sendEmail by overriding it in the unit test. This is a bit complicated to use in practice, especially since you only need to add two lines of code.






    share|improve this answer













    The problem is that Test.stopTest executes the asynchronous code, then resets the governor limits back to the state it was in immediately before Test.startTest is called. If you really wanted to verify the output, you'd need a static method to check:



    public class MyQueue implements Queueable, Database.AllowsCallouts {
    @TestVisible static Boolean emailSent = false;
    public void execute(QueueableContext context) {
    try {
    Integer invalid = 100 / 0;
    }
    catch(Exception ex) {
    sendEmail(ex);
    emailSent = true;
    }
    }
    }


    And from there, test it in your unit test:



    @IsTest
    private class MyQueue_Test {

    @IsTest
    private static void sendsEmailOnError() {

    // Exercise
    Test.startTest();
    System.enqueueJob(new MyQueue());
    Test.stopTest();

    // Verify
    System.assert(MyQueue.emailSent);
    }
    }


    This is one of those relatively rare conditions where the easiest way to perform a task is to inject test code to the actual code. You should do this minimally, of course, but as often as necessary.



    Alternatively, a more idiomatic way to do this would be to use the Stub API. The idea here is that you'd mock out sendEmail by overriding it in the unit test. This is a bit complicated to use in practice, especially since you only need to add two lines of code.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Apr 2 at 17:21









    sfdcfoxsfdcfox

    264k12210456




    264k12210456













    • Should I use Database Savepoints and rollbacks in the catch or does Apex care about this? I mean if I do some DML in the try...

      – Robert Sösemann
      Apr 2 at 21:46






    • 1





      @RobertSösemann for testing, it doesn't matter. For production code, if you perform multiple DML and do not roll back, you may leave your data in an inconsistent state. If you're at all concerned about this possibility, definitely roll back. This is on a case by case situation, though. You'll need to analyze each case separately, and determine if partial success should be allowed.

      – sfdcfox
      Apr 2 at 22:25



















    • Should I use Database Savepoints and rollbacks in the catch or does Apex care about this? I mean if I do some DML in the try...

      – Robert Sösemann
      Apr 2 at 21:46






    • 1





      @RobertSösemann for testing, it doesn't matter. For production code, if you perform multiple DML and do not roll back, you may leave your data in an inconsistent state. If you're at all concerned about this possibility, definitely roll back. This is on a case by case situation, though. You'll need to analyze each case separately, and determine if partial success should be allowed.

      – sfdcfox
      Apr 2 at 22:25

















    Should I use Database Savepoints and rollbacks in the catch or does Apex care about this? I mean if I do some DML in the try...

    – Robert Sösemann
    Apr 2 at 21:46





    Should I use Database Savepoints and rollbacks in the catch or does Apex care about this? I mean if I do some DML in the try...

    – Robert Sösemann
    Apr 2 at 21:46




    1




    1





    @RobertSösemann for testing, it doesn't matter. For production code, if you perform multiple DML and do not roll back, you may leave your data in an inconsistent state. If you're at all concerned about this possibility, definitely roll back. This is on a case by case situation, though. You'll need to analyze each case separately, and determine if partial success should be allowed.

    – sfdcfox
    Apr 2 at 22:25





    @RobertSösemann for testing, it doesn't matter. For production code, if you perform multiple DML and do not roll back, you may leave your data in an inconsistent state. If you're at all concerned about this possibility, definitely roll back. This is on a case by case situation, though. You'll need to analyze each case separately, and determine if partial success should be allowed.

    – sfdcfox
    Apr 2 at 22:25













    3














    I usually take the route of storing results in a log object as opposed to email.



    If you want, you can add a trigger to the log object to send out an email. You can enable activity tracking for the emails as well which would allow you to query for the existence of an activity as opposed to checking the governor limits.



    The benefits being:




    • logs are more permanent

    • logs are less likely to get lost in email

    • logs are not user specific meaning if there is an issue and the email recipient is out of office, the log can be viewed and the issue can be resolved

    • you can report on logs/activities but not email






    share|improve this answer






























      3














      I usually take the route of storing results in a log object as opposed to email.



      If you want, you can add a trigger to the log object to send out an email. You can enable activity tracking for the emails as well which would allow you to query for the existence of an activity as opposed to checking the governor limits.



      The benefits being:




      • logs are more permanent

      • logs are less likely to get lost in email

      • logs are not user specific meaning if there is an issue and the email recipient is out of office, the log can be viewed and the issue can be resolved

      • you can report on logs/activities but not email






      share|improve this answer




























        3












        3








        3







        I usually take the route of storing results in a log object as opposed to email.



        If you want, you can add a trigger to the log object to send out an email. You can enable activity tracking for the emails as well which would allow you to query for the existence of an activity as opposed to checking the governor limits.



        The benefits being:




        • logs are more permanent

        • logs are less likely to get lost in email

        • logs are not user specific meaning if there is an issue and the email recipient is out of office, the log can be viewed and the issue can be resolved

        • you can report on logs/activities but not email






        share|improve this answer















        I usually take the route of storing results in a log object as opposed to email.



        If you want, you can add a trigger to the log object to send out an email. You can enable activity tracking for the emails as well which would allow you to query for the existence of an activity as opposed to checking the governor limits.



        The benefits being:




        • logs are more permanent

        • logs are less likely to get lost in email

        • logs are not user specific meaning if there is an issue and the email recipient is out of office, the log can be viewed and the issue can be resolved

        • you can report on logs/activities but not email







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Apr 2 at 17:50

























        answered Apr 2 at 17:44









        gNerbgNerb

        6,086834




        6,086834






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Salesforce Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsalesforce.stackexchange.com%2fquestions%2f256225%2fsend-out-email-when-apex-queueable-fails-and-test-it%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Færeyskur hestur Heimild | Tengill | Tilvísanir | LeiðsagnarvalRossið - síða um færeyska hrossið á færeyskuGott ár hjá færeyska hestinum

            He _____ here since 1970 . Answer needed [closed]What does “since he was so high” mean?Meaning of “catch birds for”?How do I ensure “since” takes the meaning I want?“Who cares here” meaningWhat does “right round toward” mean?the time tense (had now been detected)What does the phrase “ring around the roses” mean here?Correct usage of “visited upon”Meaning of “foiled rail sabotage bid”It was the third time I had gone to Rome or It is the third time I had been to Rome

            Bunad