Writing an Apex Test Class

Everybody likes to post code that does cool stuff, but so rarely do they post the test code to get proper coverage. I usually don’t post test code either, mostly because I want people to understand the code and write the test class to be able to get it into production. Therein lies the problem. If few people are posting test code, how do you know how to write it? In this post, I’ll walk you through writing a test class for the trigger I used in my previous post, Mixing Workflow Rules and Triggers Part 2. Before you read this post, take a minute to read Apex Testing Best Practices.

First thing to look at is the various paths the code can take. We have the following scenarios that we should test:

  • Insertion of a Hot account with the user’s preference set to send email.
  • Insertion of a Hot account with the user’s preference set to not send email.
  • Update of a Cold account to and Hot account with the user’s preference set to send email.
  • Insertion of a Cold account with the user’s preference set to send email.

I quickly realize that I’m going to be doing several things repeatedly in my tests: insert accounts and change the email preference. Rather than replicate that code in each test, I’ll create a helper method to do it for me.

First, let’s take a look at setting the email preferences. I want to be able to set whether or not the running user’s preference is true or false, so I want to pass the value to the helper from my test method:

53
54
55
56
57
58
59
60
61
62
63
64
// Helper Class to update the user's email preferences
    private static void setEmailPref(Boolean pref) {
        // first get existing preferences
        EmailPref__c ep = EmailPref__c.getInstance();
        // if there aren't preferences set, create a new instance
        if (ep == null) {
            ep = new EmailPref__c();
        }
        // update the preference and upsert it
        ep.Send_Hot_Account_Email__c = pref;
        upsert ep;
    }

Next, here’s the helper method to insert accounts. There are a couple of things interesting here. First, I want to be able to insert both Hot and Cold accounts, so I’ll make that a parameter I can pass. Second, I want to test how my trigger will behave in a bulk context, so I insert 200 accounts.

66
67
68
69
70
71
72
73
74
75
76
    private static List<Account> createAccounts(String rating){
        List<Account> accts = new List<Account>();
 
        for(Integer i = 0; i < 200; i++){
            accts.add(new Account(Name = 'Test ' + i, Rating = rating));
        }
 
        insert accts;
 
        return accts;       
    }

Now we can do our actual tests. Here’s the first scenario. In it, we make sure the email preferences are set to true, reset all the limits for the test, insert our test accounts, query the accounts to get the latest values, and then check to make sure the trigger touched all our inserted accounts. You may be asking why am I checking the Decription? The reason is that I have workflow rule that clears the real value as soon as an email gets sent. Since I can’t catch the record before the workflow rule fires, in my trigger, I check to see if test are running and if so, also update the Description.

4
5
6
7
8
9
10
11
12
13
    private static testMethod void testInsertHotAccounts() {
        setEmailPref(true);
        Test.startTest();
        List<Account> insertedAccts = createAccounts('Hot');
        Test.stopTest();
 
        for (Account a : [select id, Description from Account where id in :insertedAccts]) {
            System.assertEquals('Hot Account Notification Trigger Fired', a.Description);
        }      
    }

Put it all together and here’s the final test class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
@isTest
private class HotAccountNotificationTest {
 
    private static testMethod void testInsertHotAccounts() {
        setEmailPref(true);
        Test.startTest();
        List<Account> insertedAccts = createAccounts('Hot');
        Test.stopTest();
 
        for (Account a : [select id, Description from Account where id in :insertedAccts]) {
            System.assertEquals('Hot Account Notification Trigger Fired', a.Description);
        }      
    }
 
    private static testMethod void testInsertHotAccountsNoEmail() {
        setEmailPref(false);
        Test.startTest();
        List<Account> insertedAccts = createAccounts('Hot');
        Test.stopTest();
 
        for (Account a : [select id, Description from Account where id in :insertedAccts]) {
            System.assertEquals(null, a.Description);
        }      
    }
 
    private static testMethod void testInsertColdAccounts() {
        setEmailPref(true);
        Test.startTest();
        List<Account> insertedAccts = createAccounts('Cold');
        Test.stopTest();
 
        for (Account a : [select id, Description from Account where id in :insertedAccts]) {
            System.assertEquals(null, a.Description);
        }      
    }
 
    private static testMethod void testUpdateHotAccounts() {
        setEmailPref(true); 
        List<Account> insertedAccts = createAccounts('Cold');
        for (Account a : insertedAccts) {
            a.Rating = 'Hot';
        }
 
        Test.startTest(); 
        update insertedAccts;
        Test.stopTest();
 
        for (Account a : [select id, Description from Account where id in :insertedAccts]) {
            System.assertEquals('Hot Account Notification Trigger Fired', a.Description);
        }      
    }
 
    // Helper Class to update the user's email preferences
    private static void setEmailPref(Boolean pref) {
        // first get existing preferences
        EmailPref__c ep = EmailPref__c.getInstance();
        // if there aren't preferences set, create a new instance
        if (ep == null) {
            ep = new EmailPref__c();
        }
        // update the preference and upsert it
        ep.Send_Hot_Account_Email__c = pref;
        upsert ep;
    }
 
    private static List<Account> createAccounts(String rating){
        List<Account> accts = new List<Account>();
 
        for(Integer i = 0; i < 200; i++){
            accts.add(new Account(Name = 'Test ' + i, Rating = rating));
        }
 
        insert accts;
 
        return accts;       
    }
}

Leave a Reply