0

I need to create a unit test class that will check if an ongoing email is having set the bcc and the cc, and also if the subject has been set.

I know I can get some details from the emails, as follows:

Messaging.SingleEmailMessage mail =  new Messaging.SingleEmailMessage()

Messaging.sendEmail(new Messaging.SingleEmailMessage[]{
                mail
});

mail.getSubject()
mail.getHTMLBody()

This is the only solution I know but it is ugly as I will need to change an already working project(the one I am testing) to check these values and put some System.assert(), so testing stuff will be out of the Unit test class.

My question is there any other better way I can proceed with these checks on the same very unit test class?

  • 1
    Why do you actually care? Usually it suffices to verify it gets sent. – Adrian Larson Jan 23 '17 at 17:24
2

Unlike updating fields in an SObject where you can immediately query for the fields after the DML to verify the code's unit test case set the fields, here you are in effect trying to test one of several things:

  • Did the method setBccAddresses(someList) even get called?
  • Did the argument someList have the right value(s)?

But, once the Messaging.sendEmail(..) method is called, the email is "sent" ... although in testmethods, it is never sent to a recipient. If the arguments to the sendEmail are in conflict, an exception is thrown but that is not your use case.

Since there is no equivalent to ApexPages class for outbound emails, you can't inspect an object for the 'sent' email.

The only thing I have done is to centralize my outbound email sending in a utility class that uses the fluent pattern so at least all your outbound email use cases can benefit from a consistent coding style, consistent error handling, and thus improving the likelihood that you aren't omitting something. You could take a look at this fluent pattern example

  • Yes, test that a builder sets properties correctly. Simple, effective, and reliable. This functionality deserves a utility. – Adrian Larson Jan 23 '17 at 18:04
2

I think you are stuck changing the code you are aiming to test.

Writing tests at the same time as the code being tested in general improves the design of the classes. But this is an unfortunate case where the platform doesn't provide a mock that you can wire in from the test so you have to code something ugly yourself such as:

public class Emailer {

    @TestVisible private static Messaging.SingleEmailMessage[] sentEmailMessages
            = new Messaging.SingleEmailMessage[] {};

    public static void send(Messaging.SingleEmailMessage[] emailMessages) {
        if (!Test.isRunningTest()) reallySend(emailMessages);
        else sentEmailMessages.addAll(emailMessages);
    }

    private static void reallySend(Messaging.SingleEmailMessage[] emailMessages) {
        // Limit checking
        // Call Messaging.sendEmail
        // Checking results
    }
}

and then your test code can assert the content of the sentEmailMessages array.

(If you want to get fancier, you could define your own interface and a method to allow the real send call be replaced by a mock supplied by your test.)

  • Wouldn't it be better to not test it? I mean, it's a small 3 liner method which wouldn't affect much the coverage, right? – Javier García Manzano Aug 15 '17 at 13:34
  • 1
    @JavierGarcíaManzano Main point of tests is that they assert that the code works today and in the future. Code coverage is a basic metric that demonstrates some effort has been made. If correct emails matter the test is worth writing. – Keith C Aug 15 '17 at 16:37

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.