2

I Have the following class but Im stuck at how to write a untit test for email messaging I have the following:

public class SendemailController {
    public String OpportunityId {
        get;
        set;
    }

    Public SendemailController() {
        OpportunityId = ApexPages.currentPage().getParameters().get('Id');
    }

    Public Pagereference sendEmailFunction() {
        Opportunity getEmail = [SELECT Id, Contact__r.email FROM Opportunity WHERE id =: OpportunityId];
        if (getEmail.Contact__r.email != null) {
            String toaddress = getEmail.Contact__r.email;

            Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
            String[] toAddresses = new String[] {
                toaddress
            };
            String[] ccAddresses = new String[] {
                toaddress
            };
            mail.setToAddresses(toAddresses);
            mail.setCcAddresses(ccAddresses);
            mail.setReplyTo(toaddress);
            mail.setSenderDisplayName('Name');
            mail.setSubject('Testing email through apex');
            mail.setBccSender(false);
            mail.setUseSignature(true);
            mail.setPlainTextBody('Dear tester, here are the attechments. This mail is sent trough apex');

            List < Messaging.Emailfileattachment > fileAttachments = new List < Messaging.Emailfileattachment > ();
            for (Attachment a: [select Name, Body, BodyLength from Attachment where ParentId =: OpportunityId]) {
                Messaging.Emailfileattachment efa = new Messaging.Emailfileattachment();
                efa.setFileName(a.Name);
                efa.setBody(a.Body);
                fileAttachments.add(efa);
            }

            mail.setFileAttachments(fileAttachments);
            Messaging.sendEmail(new Messaging.SingleEmailMessage[] {
                mail
            });
        }
        PageReference reference = new PageReference('https://eu11.salesforce.com/' + OpportunityId);
        reference.setRedirect(true);
        return reference;
    }
}

Test Class

@IsTest
public class SendemailControllerTestClass {

    @IsTest private static void SendemailControllerTestClass() {
        Contact con = new Contact();
        con.FirstName = 'TestName';
        con.LastName = 'TestLastname';
        con.Email = '[email protected]';
        insert con;

        Opportunity oppNew = new Opportunity();
        oppNew.Name = 'Test Opp';
        oppNew.StageName = 'Ticketing';
        oppNew.CloseDate = System.now().date();
        insert oppNew;

        test.startTest();
        PageReference pageRef = Page.Email_Attachments;
        Test.setCurrentPage(pageRef);

        pageRef.getParameters().put('id',oppNew.id);
        ApexPages.StandardController sc = new     ApexPages.standardController(oppNew);
        Pagereference controller = Page.Email_Attachments;
        controller.sendEmailFunction();
        test.stopTest();

    }
}
1
  • 1
    Why are you sending an email in your test class? Your apex class sends the email, you need to replicate the conditions required for your apex class to produce the expected and unexpected outcomes. Seems your class is a Visualforce controller so you will need to at a minimum instantiate the controller, set the appropriate properties and execute and validate the methods. This is a good starting point as it seems you may have not captured the basics of testing yet: trailhead.salesforce.com/en/modules/apex_testing
    – Eric
    Feb 27, 2017 at 22:39

3 Answers 3

3

Typically, all you can validate is that an email send was invoked.

Test.startTest();
    methodWhichSendsEmail();
    Integer emailInvocations = Limits.getEmailInvocations();
Test.stopTest();

system.assertEquals(1, emailInvocations, 'An email should be sent');

If you want to get more sophisticated than that, you'll likely need to write an email builder utility where you can assert on more granular behavior about a single message.

1
  • I tried: Test.startTest(); SendemailController.sendEmailFunction Pagereference Email = new SendemailController.sendEmailFunction(); Integer emailInvocations = Limits.getEmailInvocations(); Test.stopTest(); system.assertEquals(1, emailInvocations, 'An email should be sent'); I get the error: expecting a semi-colon, found 'Email'
    – user42169
    Feb 28, 2017 at 13:05
1

In addition to @Adrian Larson's answer, you can create an EmailService, and ensure that gets called with the parameters you expect. An easy way to do this would be to use Dependency Injection to pass in an EmailService implementation, and then in your test use a MockedImplementation.

public class SendEmailController {


    Public SendemailController() {
        OpportunityId = ApexPages.currentPage().getParameters().get('Id');
    }

    Public Pagereference sendEmailFunction() {
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        List<Messaging.SingleEmailMessage> mails= new List<Messaging.SingleEmailMessage>{mail};
        EmailService.getImpl().sendEmail(mails);
    }

Email Service class

public class EmailService implements API {

    public interface API {
        void sendEmail(Messaging.SingleSendEmail[] emails);
    }

    private API impl;
    public static getImpl() {
        if (impl != null)
            return impl;

        return (API) new EmailService();
    }

    public static setImpl(API impl) {
        this.impl = impl;
    }
}

SendEmailControllerTest class

@IsTest
public class SendemailControllerTestClass {
    public class MockEmailService implements EmailService.API {
        public List<Messaging.SingleSendEmail> emails;
        public void sendEmail(Messaging.SingleSendEmail[] emails) {
            this.emails = emails;
        }
    }

    @IsTest
    public static void testEmailSend()
    {
        MockEmailService impl = new MockEmailService();

        EmailService.setImpl(impl);

        // Run the code under test
        new SendEmailController().sendEmailFunction();

        // Check an email was sent
        Messaging.SingleEmailMessage expectedMessage = new Messaging.SingleEmailMessage();
        List<Messaging.SingleEmailMessage> expectedMessages = new List<Messaging.SingleEmailMessage>{expectedMessage};

        System.assertEquals(impl.Emails, expectedMessages, 'Got unexpected emails');
    }
}

Some useful reading: ApexMocks https://github.com/financialforcedev/fflib-apex-mocks Apex Enterprise Patterns: https://developer.salesforce.com/page/Apex_Enterprise_Patterns_-_Separation_of_Concerns

0

For anyone who bumps into this problem here is how i resolved this:

@isTest
private class SendemailControllerTest{

    static testMethod void test () {

        Account acc = new Account();  
        acc.Name = 'test';  

        insert acc; 

        Contact con = new Contact();
        con.Lastname = 'test';
        con.email = '[email protected]';

        insert con;

        Opportunity opp = new Opportunity();
        opp.StageName = 'In Progress';
        opp.Name = 'test'; 
        opp.Contact__c = con.id;
        opp.CloseDate = System.today();
        opp.AccountId = acc.id;

        insert opp; 

        Attachment att = new Attachment();
        att.Name = 'test';
        att.Body = Blob.ValueOf('test');
        att.ParentId = opp.id;

        Insert att;

        ApexPages.currentPage().getParameters().put('Id',opp.id);   
        SendemailController Controller = new SendemailController();

        Controller.sendEmailFunction();
    }
}

You must log in to answer this question.

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