I am very new to the model-view-controller and have barely been able to get my code functional, but now I'm struggling even more trying to write test code! This is my first wrapper class, controller extension, and test classes for those, so sorry if my code is ugly, but hopefully what I'm asking makes sense!

I have a VF form that allows users to add OrderProducts to an Order that basically clone the QuoteLineItems on the related Quote, except that you can adjust the Quantity, to allow for multiple Orders from a Quote (this was the requirement).

I'm trying to write tests for this, but am unable to refer to the input variable on my VF page, I keep getting a "variable does not exist" error, so I'm unable to test the ProcessSelected() method, I think.

I saw this question here: Test visualforce form submission which makes it sound like referring to the variable is very simple, but I'm still unable to get it.

Ultimately, I'm looking to test different inputs (equal to/greater than/less than Quote.Quantity) on the VF form, and how my controller reacts to those values.


Here is my controller:

public class addOrderProductsController {

public final Order ord;

public addOrderProductsController(ApexPages.StandardController controller){
    this.ord = (Order)Controller.getRecord();

//Our collection of the class/wrapper objects cQuoteLineItem 
public static List<cQuoteLineItem> QuoteLineItemList {get; set;}

//This method uses a simple SOQL query to return a List of QuoteLineItems
public static List<cQuoteLineItem> getQuoteLineItems() {
    if(QuoteLineItemList == null) {
        string q = system.currentPageReference().getParameters().get('Id');
        Order SalesOrder = [select Id, QuoteId from Order where Id =: q];
        system.debug('SalesOrder ' + SalesOrder);
        QuoteLineItemList = new List<cQuoteLineItem>();
        for(QuoteLineItem c: [SELECT Id, Part_Number__c, Product2.Name, PricebookEntryId, Unit_Price_Discounted__c, UnitPrice, Quantity, 
                              List_Price_Subtotal__c, TotalPrice, Quantity_Selected__c, Available_Quantity__c, Description, Support_Tag__C
                              from QuoteLineItem where QuoteId =: SalesOrder.QuoteId]) {
            // As each QuoteLineItem is processed we create a new cQuoteLineItem object and add it to the QuoteLineItemList
            system.debug('Qli C ' + c);
            QuoteLineItemList.add(new cQuoteLineItem(c));
    return QuoteLineItemList;       

public PageReference processSelected() {

    //We create a new list of QuoteLineItems that we be populated only with QuoteLineItems if they are selected
    List<QuoteLineItem> selectedQuoteLineItems = new List<QuoteLineItem>();
    //Pricebook2Id needs to be set for the Order before Order Products can be added.
    string oid = System.currentPageReference().getParameters().get('Id');
    Order o = [Select Id,QuoteId,Pricebook2Id from Order where Id =: oid];
    Quote q = [Select Id,Pricebook2Id from Quote where Id=: o.QuoteId];
    o.Pricebook2Id = q.Pricebook2Id;
    update o;
    //We will cycle through our list of cQuoteLineItems and will check to see if the quantity selected is greater than 0, less than the Quantity Available, and not null 
    //if it is we add the QuoteLineItem to the selectedQuoteLineItems list, if not, Error Message
    integer errCount = 0;
    for(cQuoteLineItem cCon: getQuoteLineItems()) {
        if(cCon.quantitySelected != null && cCon.quantitySelected <= cCon.con.Quantity) {
            cCon.con.Quantity_Selected__c = cCon.quantitySelected;
        else {
    // Error Message 
    if (errCount > 0) {

        ApexPages.Message errormsg = new ApexPages.Message(ApexPages.severity.ERROR, 'Quantity on Order Items cannot exceed Quantity of Quote Items');
        return null;

    // Now we have our list of selected QuoteLineItems and can create new OrderProducts with the QuoteLineItem's field values
    List<OrderItem> OrderItemstoAdd = new List<OrderItem>();
    for(QuoteLineItem con: selectedQuoteLineItems) {
        if(con.Quantity_Selected__c > 0){
        OrderItem op = new OrderItem(Quantity = con.Quantity_Selected__c, 
                                     PricebookEntryId = con.PricebookEntryId,
                                     PricebookEntry = con.PricebookEntry,
                                     Discount__c = con.Discount,
                                     UnitPrice = con.UnitPrice,
                                     Total_Price__c = con.TotalPrice,
                                     OrderId = oid,
                                     Description = con.Description);
        insert OrderItemstoAdd;
        QuoteLineItemList=null; // we need this line if we performed a write operation  because getQuoteLineItems gets a fresh list now
        PageReference pr = new ApexPages.StandardController(o).view();
        return pr;
        ApexPages.Message errmsg = new ApexPages.Message(ApexPages.severity.ERROR, 'No Orders Added. Please check that Quantity Selected does not exceed Quantity available.');
        return null;

// This is our wrapper/container class. A container class is a class, a data structure, or an abstract data type whose instances are collections of other objects. 
// In this example a wrapper class contains both the standard salesforce object QuoteLineItem and an integer value
public class cQuoteLineItem {
    public QuoteLineItem con {get; set;}
    public Integer quantitySelected {get; set;}

    //This is the contructor method. When we create a new cQuoteLineItem object we pass a QuoteLineItem that is set to the con property. 
    //We also set the selected value to false
    public cQuoteLineItem(QuoteLineItem c) {
        con = c;
        quantitySelected = integer.valueOf(c.Quantity);

Here is my VF Page:

<apex:page standardController="Order" extensions="addOrderProductsController" docType="html-5.0">
<apex:form >
    <apex:pageBlock >
        <apex:pageMessages />
        <apex:pageBlockButtons >
            <apex:commandButton value="Add Selected Line Items" action="{!processSelected}"/>
        <!-- In our table we are displaying the cQuoteLineItem records -->
        <apex:pageBlockTable value="{!QuoteLineItems}" var="c" id="table">
            <apex:column >
                <!-- This is our selected Quantity integer property in our wrapper class -->
                <apex:input type="number" value="{!c.quantitySelected}"/>
            <!-- This is how we access the QuoteLineItem values within our cQuoteLineItem container/wrapper -->
            <apex:column value="{!c.con.Quantity}" />
            <apex:column value="{!c.con.Part_Number__c}" />
            <apex:column value="{!c.con.Product2.Name}" />
            <apex:column value="{!c.con.Unit_Price_Discounted__c}" />
            <apex:column value="{!c.con.UnitPrice}" />
            <apex:column value="{!c.con.List_Price_Subtotal__c}" />
            <apex:column value="{!c.con.TotalPrice}" />  
            <apex:column value="{!c.con.Description}" />            

And here are my tests thus far:

private class addOrderProductsController_Tests {

private static User testUser;
private static Account testAcc;
private static Contact testcon;
private static Opportunity testOpp;
private static Product2 testSWprod;
private static Product2 testHWprod;
private static Product2 testSPTprod;
private static Product2 testSVCprod;
private static Id pbid;
private static PricebookEntry testSWpbe;
private static PricebookEntry testHWpbe;
private static PricebookEntry testSPTpbe;
private static PricebookEntry testSVCpbe;
private static Quote testQuote;
private static QuoteLineItem testSWqli;
private static QuoteLineItem testHWqli;
private static QuoteLineItem testSPTqli;
private static QuoteLineItem testSVCqli;
private static Order testOrd;

    //create test records
    testUser = [select Id from User where isActive=true AND IsPortalEnabled=false limit 1];
    testAcc = new Account(Name = 'testAcc', Market__c = 'Commercial', Region__c = 'West');
    testCon = new Contact(FirstName = 'test', LastName = 'Contact', AccountId = testAcc.Id);
    testOpp = new Opportunity(Name = 'testOpp', AccountId=testAcc.Id, Capacity_Usable_TB__c=10, Interface__c = 'S3', CloseDate = date.today(), StageName='Identified');

    insert testAcc;
    insert testCon;
    insert testOpp;

    testSWprod = new Product2(Name = 'testSWprod', Product_Type__c = 'SW', Part_Number__c = 'SWPN', isActive=true);
    testHWprod = new Product2(Name = 'testHWprod', Product_Type__c = 'HW', Part_Number__c = 'HWPN', isActive=true, Product_cost__c = 1);
    testSPTprod = new Product2(Name = 'testSPTprod', Product_Type__c = 'SPT', Part_Number__c = 'SPTPN', isActive=true);
    testSVCprod = new Product2(Name = 'testSVCprod', Product_Type__c = 'SVC', Part_Number__c = 'SVCPN', isActive=true);

    insert testSWprod;
    insert testHWprod;
    insert testSPTprod;
    insert testSVCprod;

    pbid = test.getStandardPricebookId();

    testSWpbe = new PricebookEntry(pricebook2id = pbid, product2id = testSWprod.id, unitprice = 1.0, isActive=true);
    testHWpbe = new PricebookEntry(pricebook2id = pbid, product2id = testHWprod.id, unitprice = 1.0, isActive=true);
    testSPTpbe = new PricebookEntry(pricebook2id = pbid, product2id = testSPTprod.id, unitprice = 1.0, isActive=true);
    testSVCpbe = new PricebookEntry(pricebook2id = pbid, product2id = testSVCprod.id, unitprice = 1.0, isActive=true);

    insert testSWpbe;
    insert testHWpbe;
    insert testSPTpbe;
    insert testSVCpbe;

    testQuote = new Quote(Name = 'testQuote', OpportunityId = testOpp.id, Pricebook2Id = pbid, ExpirationDate = date.today().addYears(1), ContactId = testCon.Id, Point_of_Contact__c = testUser.Id);

    insert testQuote;

    testSWqli = new QuoteLineItem(PricebookEntryId=testSWpbe.id, QuoteId=testQuote.id, UnitPrice = 1, Quantity = 10);
    testHWqli = new QuoteLineItem(PricebookEntryId=testHWpbe.id, QuoteId=testQuote.id, UnitPrice = 1, Quantity = 10);
    testSPTqli = new QuoteLineItem(PricebookEntryId=testSPTpbe.id, QuoteId=testQuote.id, UnitPrice = 1, Quantity = 10, Support_Tag__c = 'abcd');        
    testSVCqli = new QuoteLineItem(PricebookEntryId=testSVCpbe.id, QuoteId=testQuote.id, UnitPrice = 1, Quantity = 10);        

    insert testSWqli;
    insert testHWqli;
    insert testSPTqli;
    insert testSVCqli;      

    testOrd = new Order(Name = 'testOrd', AccountId = testAcc.id, EffectiveDate = date.today(), Status = 'Draft', QuoteId = testQuote.Id, Pricebook2Id = pbid);

    insert testOrd;
//test getQuoteLineItems
static testMethod void testGetQuoteLineItems(){
    system.currentPageReference().getParameters().put('Id', testOrd.id);
    string q = system.currentPageReference().getParameters().get('Id');
    system.debug('testOrd.Id = '+ q);

    List<addOrderProductsController.cQuoteLineItem> QuoteLineItemList = addOrderProductsController.getQuoteLineItems();
    system.debug('test result ='+ QuoteLineItemList);

//test processSelected, set QuantitySelected to 10
static testMethod void testProcessSelectedEqualtoQuantity(){
    PageReference pageRef = page.AddOrderProducts;
    ApexPages.StandardController sc = new ApexPages.standardController(testOrd);
    addOrderProductsController controller = new addOrderProductsController(sc);
    controller.QuoteLineItems;  // <-- variable does not exist
    controller.quantitySelected = 10;  // <-- variable does not exist


//test processSelected, set QuantitySelected to 11
static testMethod void testProcessSelectedGreaterThanQuantity(){

//test processSelected, set QuantitySelected to 9
static testMethod void testProcessSelectedLessThanQuantity(){


  • 2
    Your controller variable refers to an object of type addOrderProductsController but the reference to QuoteLineItems won't work as there is no controller instance variable named QuoteLineItems. QuantitySelected is defined in the inner class and in order to set it in a testmethod, you will need to instantiate the inner class first – cropredy Oct 24 '14 at 19:39
  • Thanks for the comment crop! Can you explain how to instantiate the inner class for quantity selected? I've tried addOrderProductsController.getQuoteLineItems() and addOrderProductController.processSelected() which are both valid, but don't let me call the quantitySelected variable. addOrderProductController.cQuoteLineItem() isn't valid, but that's where the variable quantitySelected sits! – k shen Oct 24 '14 at 21:27

First of all, get rid of the static modifier on these two lines -- they should be instance variables/instance methods

public static List<cQuoteLineItem> QuoteLineItemList {get; set;} // remove static

public static List<cQuoteLineItem> getQuoteLineItems() { .. // remove static

Variable QuantitySelected exists on an inner class so your testmethod has to create the list of cQuoteLineItems first as in:

static testMethod void testProcessSelectedEqualtoQuantity(){
PageReference pageRef = page.AddOrderProducts;
ApexPages.StandardController sc = new ApexPages.standardController(testOrd);
addOrderProductsController controller = new addOrderProductsController(sc);
controller.getQuoteLineItems();  // build QuoteLineItemList
controller.QuoteLineItemList[0].quantitySelected = 10; // set first QLI with a selected qty

PageReference resPg = controller.processSelected();
// do asserts here by verifying resPg.getUrl(), querying database, 
//   examining apexPages.currentPage().getmessages() - an exercise for you
  • Thanks a ton for the help, I finally got the asserts done, and applied this to the other test methods for my class as well! – k shen Oct 30 '14 at 21:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.