Question:

Trouble creating test to cover code

Arya: 2 weeks ago

I'm working on a trigger that will email users when a specific field is changed. I am having trouble creating a test class that will give me proper code coverage. I am new to this kind of thing so help creating a test class would be appreciated:

trigger onChange on Account (after update) {
    for (Account acc: Trigger.new) {
        Account oldAccount = Trigger.oldMap.get(acc.ID);
        if (acc.Group_ID__c != oldAccount.Group_ID__c) {
            Messaging.reserveSingleEmailCapacity(2);
            Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
            String[] toAddresses = new String[] {'email@email1.com','email@email2.com','email@email3.com'};        
            mail.setToAddresses(toAddresses);
            mail.setSenderDisplayName('Salesforce Support');
            mail.setSubject('Group ID Changed: '+ acc.Name);
            mail.setPlainTextBody('The Group ID of '+acc.Name+' has changed from: \n'+ oldAccount.Group_ID__c + '\n to \n' + acc.Group_ID__c);
            Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
        }
    }
}

Here's what I got for my test so far:

public class testDataOnChange {

   public static Account createAccount(Boolean item){
       Account acc = Account();

    }
    public static Account createAccount(String thename){
        Account acc = new Account(
            Name = thename,
            Group_ID__c = 'as344'
        );
        insert acc;
        return acc;
    }
}

Answer:
Chloe: 2 weeks ago

You have a particularily difficult example to test for a beginner.

First, the usual clarification:

  • Tests are not to provide test coverage, but to verify that your business logic is correct.

Having said that, I can give you some tips about your tests:

  • Your test class and methods need to be annotated with @isTest to be ran as tests
  • Your test needs to actually exercise your trigger. In a few words, your trigger runs on account update, and if the group ID has changed, send an email. So, your test class needs to update an account and change the group ID so that the trigger fires, then assert that the email has been sent.
  • You can cover more cases: for instance, update the account without changing the group ID, and check that the email is not sent.
  • I found a clever way to verify that the email has been sent, in this question: How to test if outbound email is send (https://salesforce.stackexchange.com/questions/13089/how-to-test-if-outbound-email-is-send)

So, your test class could look like this:

@isTest
public class testDataOnChange {

    @isTest
    public static void emailIsSentIfGroupIdChanges ()
    {
        Account acct = new Account (Name = 'Test', Group_ID__c = 'Original');
        insert acct;          

        System.startTest ();
        acct.GroupId__c = 'Modified';
        update acct;  // This should fire your trigger and send email
        System.endTest ();

        System.AssertEquals (1, Limits.getEmailInvocations());
    }

    @isTest
    public static void emailIsNotSentIfGroupIdDoesNotChange ()
    {
        Account acct = new Account (Name = 'Test', Group_ID__c = 'Original');
        insert acct;          

        System.startTest ();
        acct.Name = 'Modified';
        update acct;  // This should fire your trigger but not send email
        System.endTest ();

        System.AssertEquals (0, Limits.getEmailInvocations());
    }
}

Disclaimer: I haven't actually ran this test. It's just an idea on how you could do it.

Edit: I have also added the case for when your group Id does not change and your email is not sent.

There's some code repetition in there. You could easily extract common code paths to a common method, but I think this way the test is clearly illustrated.