Newer Version Available

This content describes an older version of this product. View Latest

Testing Custom Controllers and Controller Extensions

Controller extensions and custom controllers, like all Apex scripts, should be covered by unit tests. Unit tests are class methods that verify whether a particular piece of code is working properly. Unit test methods take no arguments, commit no data to the database, and are flagged with the testMethod keyword in the method definition.

When writing unit tests for controller extension and custom controller classes, you can set query parameters that can then be used in the tests. For example, the following custom controller and markup is based on the example from Controller Methods, but has been extended to expect the following query parameter in the URL for the page: ?qp=yyyy. A test method class follows, which exercises the functionality of this page:

1swfobject.registerObject("clippy.codeblock-0", "9");
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public class thecontroller {
18
19            private String firstName;
20            private String lastName;
21            private String company;
22            private String email;
23            private String qp;
24
25            public thecontroller() {
26                this.qp = ApexPages.currentPage().getParameters().get('qp');
27            }
28
29            public String getFirstName() {
30                  return this.firstName;
31            }
32
33            public void setFirstName(String firstName) {
34                  this.firstName = firstName;
35            }
36
37            public String getLastName() {
38                  return this.lastName;
39            }
40
41            public void setLastName(String lastName) {
42                  this.lastName = lastName;
43            }
44
45            public String getCompany() {
46                  return this.company;
47            }
48
49            public void setCompany(String company) {
50                  this.company = company;
51            }
52
53            public String getEmail() {
54                  return this.email;
55            }
56
57            public void setEmail(String email) {
58                  this.email = email;
59            }
60
61            public PageReference save() {
62                PageReference p = null;
63                
64                if (this.qp == null || !'yyyy'.equals(this.qp)) {
65                    p = Page.failure;
66                    p.getParameters().put('error', 'noParam');
67                } else {
68                    try {
69                        Lead newlead = new Lead(LastName=this.lastName, 
70                                                FirstName=this.firstName, 
71                                                Company=this.company, 
72                                                Email=this.email);
73                        insert newlead;
74                    } catch (Exception e) {
75                        p = Page.failure;
76                        p.getParameters().put('error', 'noInsert');
77                    }
78                }
79                
80                if (p == null) {
81                    p = Page.success;
82                }
83                
84                p.setRedirect(true);
85                return p;
86            }
87 }
The controller calls two additional pages: a success page and a failure page. The text of those pages is not important for this example. They merely have to exist.

The following markup uses the controller above:

1swfobject.registerObject("clippy.codeblock-3", "9");
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17<apex:page controller="thecontroller" tabstyle="lead">
18   <apex:pageBlock>
19      <apex:form>
20         <h1>Test page for adding leads</h1>
21         <p>This is a test page for adding leads.</p>
22         <p>First name: <apex:inputText value="{!FirstName}"></apex:inputText></p>
23         <p>Last name: <apex:inputText value="{!LastName}"></apex:inputText></p>
24         <p>Company: <apex:inputText value="{!Company}"></apex:inputText></p>
25         <p>Email address: <apex:inputText value="{!Email}"></apex:inputText></p>
26         <apex:commandButton action="{!save}" value="Save New Lead"/>
27      </apex:form>
28   </apex:pageBlock>
29</apex:page>

The following class tests the controller:

1swfobject.registerObject("clippy.codeblock-4", "9");
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17@isTest
18public class thecontrollerTests {
19
20    public static testMethod void testMyController() {
21        PageReference pageRef = Page.success;
22        Test.setCurrentPage(pageRef);
23      
24        thecontroller controller = new thecontroller();
25        String nextPage = controller.save().getUrl();
26
27        // Verify that page fails without parameters
28        System.assertEquals('/apex/failure?error=noParam', nextPage);
29
30        // Add parameters to page URL
31        ApexPages.currentPage().getParameters().put('qp', 'yyyy');
32      
33        // Instantiate a new controller with all parameters in the page
34        controller = new thecontroller(); 
35        controller.setLastName('lastname');
36        controller.setFirstName('firstname');
37        controller.setCompany('acme');
38        controller.setEmail('firstlast@acme.com');
39        nextPage = controller.save().getUrl();
40
41        // Verify that the success page displays
42        System.assertEquals('/apex/success', nextPage);
43        Lead[] leads = [select id, email from lead where Company = 'acme'];
44        System.assertEquals('firstlast@acme.com', leads[0].email);
45    }
46}

If you are testing your controller you may see the following error message:

1Method does not exist or incorrect signature: Test.setCurrentPage(System.PageReference)

Tip