1. Template for testing Controller Extension

For this example we will use page: my_VFPage which standard controller use my_Object__c and has extension controller my_VFPage_Controller.
It can also have two parameters "type" and "size" so full call URL look like that:


Visualforce Code:

<apex:page standardController="my_Object__c" extensions="my_VFPage_Controller">
    <!-- Page contet -->

Example Apex test method:

public class my_customVisualforcePage_Controller_Test {

    public static testMethod void test_firstTestCase() {
        /************ Configure enviroment ************/
        /**** Prepare database structure ****/
        // Create Account
        Account accountRecord = my_TestHelper.createTestAccount(TRUE);
        // Insert order
        myCutomOrder__c orderRecord = my_TestHelper.createTestOrder(FALSE);
        orderRecord.Account__c = accountRecord.Id;
        insert orderRecord;
        /**** Set page in context ****/

        /**** Set url parameters ****/
        pageRef.getParameters().put('type', 'car');
        pageRef.getParameters().put('size', 'small');
        /**** Set Controller in context ****/
        my_VFPage_Controller controllerExt = new my_VFPage_Controller(
            new ApexPages.StandardController(new my_Object__c())
        /************** Start testing *************/

Prepare database structure is optional if you do not make any calls to database for searching existing records.
Read more about it in article Test Helper class

Order is very important here:
- firstly you must select the page which will be used
- secondly set all URL parameters
- then initiate controller

2. Template for testing Controller

If your page is using only custom controller then modify code above.

Visualforce Code:

<apex:page controller="my_VFPage_Controller">
    <!-- Page contet -->

In Apex test method replace "//Set ControllerExtension in context" with:

        /**** Set Controller in context ****/
        my_VFPage_Controller controller = new my_VFPage_Controller());

3. Insert test records to database.

You should create separate TestHelper class where all methods for record creation are placed. See article Test Helper class section Classes for preparing database structure.

Example code which create my_CustomObject__c object immediately:

Account a = myTestHelper.createAccount(TRUE);
my_CustomObject__c mco = myTestHelper.createMyCustomObject(a.Id, TRUE);

alternatively if you want to fill in more fields in it you may write:

Account a = myTestHelper.createAccount(TRUE);
my_CustomObject__c mco = myTestHelper.createMyCustomObject(a.Id, FALSE);
mco.comment__c = 'abcd';
mco.Quantity__c = 6; // override default value from helper class

insert mco; // insert modified object

4. Reading page error messages.

In Controller constructor we check if clientId is provided in URL. As it is reqired for next actions not giving it lead to error.
Please see Read and write URL parameters values for more details when it is null or empty string.

public newOrderController(ApexPages.StandardController controller) {
    if (clientId == '' || clientId == null) {
        String errorMsg = 'No client Id provided.';
        ApexPages.addmessage(new ApexPages.message(ApexPages.severity.WARNING, errorMsg));
    } else {
      /* */

Simulate not providing clientId and read error from page.

public static testMethod void test_NewOrder_noClientId() {
    /************ Configure enviroment ************/
    /**** Prepare database structure ****/        
    Order__c cmo = new Order__c();
    /**** Set page in context ****/
    /**** Set url parameters ****/
    // ApexPages.currentPage().getParameters().put('scId', sc.Id);    
    /**** Set Controller in context ****/ 
    newOrderController controllerExt = new newOrderController (new ApexPages.StandardController(cmo) );  
    /************** Start testing *************/

    // Read error messages from page and check if there is one which we expect
    List<Apexpages.Message> msgList = ApexPages.getMessages();
    System.assertEquals(1, msgList.size());
    System.assertEquals('No client Id provided.', msgList.get(0).getSummary()); 
    System.assertEquals(ApexPages.Severity.WARNING, msgList.get(0).getSeverity());

Apex Page Messages

5. Simualte filling fileds by user.

In this case our VF Page has few fields where user type values. We want to simulate this process.

In this case data will be saved to custom object client_Order__c.

VF Page code:

<apex:page standardController="client_Order__c" extensions="newOrderController">
/* */
<apex:inputField value="{!client_Order__c.orderName__c}" />
<apex:inputField value="{!client_Order__c.amount__c}" />

Controller code:

public with sharing class newOrderController {
    // Global variables
    client_Order__c clientOrderObj;

    // Constructor
    public newOrderController(ApexPages.StandardController stdController) {
        clientOrderObj = (client_Order__c)stdController.getRecord(); 

Test Class code:

/**** Prepare database structure ****/
client_Order__c clo = new client_Order__c();

/**** Set Controller in context ****/ 
newOrderController controllerExt = new newOrderController (new ApexPages.StandardController(clo) );

We created empty representation of client_Order__c object named clo and passed it to standard controller.

Now we can change it's values:

clo.orderName__c = 'Test Order';
clo.amount__c = '123';

and then execute some controller action like save:


Then you need to check if it is saved correctly.

// Checking if saved properly
client_Order__c cli2 = new client_Order__c();
cli2 = [SELECT orderName__c, amount__c FROM client_Order__c WHERE Id = :cli.Id];
System.assertEquals(cli.orderName__c, cli2.orderName__c);
System.assertEquals(cli.amount__c, cli2.amount__c);

Test Save and Cancel button

Visualforce code:

<apex:pageBlockButtons >
    <apex:commandButton value="Save" action="{!doSave}"/>
    <apex:commandButton value="Cancel" action="{!doCancel}" immediate="TRUE"/>

Controller extension code:

/* Save */
public PageReference doSave() {
    PageReference pr = Page.myOrderDetails;
    pr.getParameters().put('orderId', orderId);
    return pr;

/* Cancel */
public PageReference doCancel() {
    PageReference pr = Page.myOrdersList;
    return pr;

Test Class code:

At the top you should begin with example from paragraph "Testing Controller Extensions", then under variable "controllerExt" you will have an access to all controller variables and methods.

// orderId = order.Id // Firstly create and insert Order to database.

// Save button
System.assertEquals('/apex/myorderdetails', controllerExt.doSave().getUrl() );
System.assertEquals(orderId, controllerExt.doSave().getParameters().get('orderId') );

// Cancel button
System.assertEquals('/apex/myorderslist', controllerExt.doCancel().getUrl() );

System.asserEquals is case sensitive. Use low cases for assertion URL String as getUrl() returns lower case string.
For methods available on PageReference class see SF documentation PageReference Class.

Additional materials:

Testing Custom Controllers and Controller Extensions
StandardController Class
PageReference Class
System Methods

© Paweł Woźniak