function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Jason DunphyJason Dunphy 

Unit Testing Help For Apex Class Controller Extension (Extension Just Passes Basic Record Values To Visualforce Page Fields)

Hi,

I’m new to Salesforce apex and I'm trying to create the unit testing for a controller extension.  The extension just grabs basic values from the page the user is currently on and populates them on a new visual force creation page.  (e.g. user is on an order record, clicks create new visual force page and the account id and order id from the page carries over to the yet unsaved VF record).  I’ve been combing through posts and examples to come up with proper unit testing, but I haven’t found anything that seems to works for me yet.  I think what I might be getting thrown on is that my controller extension isn’t committing anything, just pre-populating values on the new page that the user will continue to edit and then save when they finish filling out all the applicable values.

Any help and guidance would be greatly appreciated.

Here's the VF page:
<apex:page sidebar="false" StandardController="Cust_Credit__c" extensions="CreditExtension">
    <apex:form >
        <apex:pageBlock title="Create A New Credit">
            <apex:pageBlockSection title="My Content Section" columns="2">
                <apex:inputField value="{!Cust_Credit__c.Credit_Memo_Account__c}"/>
                <apex:inputField value="{!Cust_Credit__c.Credit_Memo_Details__c}"/>
                <apex:inputField value="{!Cust_Credit__c.Credit_Memo_Item__c}" required="true"/>
                <apex:inputField value="{!Cust_Credit__c.Credit_Amount__c}"/>
                <apex:inputField value="{!Cust_Credit__c.Related_Order__c}"/>
            </apex:pageBlockSection>
        </apex:pageBlock>
            <apex:commandButton action="{!save}" value="Save" id="theButton"/>
    </apex:form>
</apex:page>

Here's the controller extension:
public class CreditExtension {
    Cust_Credit__c custCred {get;set;}

    public CreditExtension(ApexPages.StandardController stdController){
        custCred = (Cust_Credit__c)stdController.getRecord();
        custCred.Credit_Account__c = ApexPages.currentPage().getParameters().get('AccountId');
        custCred.Related_Order__c = ApexPages.currentPage().getParameters().get('OrderId');
    }
}
Here's the URL from the custom button that hits the controller extension/VF page:
/apex/Credit_Memo_Entry?AccountId={!Account.Id}&OrderId={!Order.Id}
And here's my poor attempt at a unit test:
@IsTest public with sharing class CreditMemoControllerTest {
     @IsTest(SeeAllData=true) public static void testCreditMemoControllerTest() {
        CreditExtension controller = new CreditExtension();
        controller.setAccountId('001C000001Iqyqa');    
        controller.setOrderId('801C00000008fYW');               
        System.assertEquals(controller.CreditExtension(),null);                           
    }    
}

Thanks

 
Best Answer chosen by Jason Dunphy
Saurabh BSaurabh B
Hi Jason, please try below and let me know if it works ...
 
@isTest
public class creditMemoTest {

    public static testMethod void testMyController() 
    {
        Account acc = new Account();
        acc.Name ='Test Account';
        insert acc; 
        
       Cust_Credit__c obj = new Cust_Credit__c (Credit_Memo_Account__c =acc.id);
         obj.Credit_Amount__c = 200.00;
         insert obj;

        PageReference pageRef = Page.Credit_Memo_Entry;
        Test.setCurrentPage(pageRef);
        
        
        ApexPages.Standardcontroller sc = new ApexPages.Standardcontroller(obj);
        ApexPages.currentPage().getParameters().put('AccountId',obj.Credit_Memo_Account__c);
        ApexPages.currentPage().getParameters().put('OrderId',obj.Related_Order__c);

        
        CreditExtension ec = new CreditExtension (sc);
    } 
}

If it still doesnt work, go to your Master-Detail field and try enabling "Allow Reparenting" option and try running test again.

All Answers

Saurabh BSaurabh B
Hi Jason, this should do it. At line 8, please replace/add name of your VF page.
 
@isTest
public class thecontrollerTests {

    public static testMethod void testMyController() {
         Cust_Credit__c obj = new Cust_Credit__c(Name ='Test');
         insert obj;

PageReference pageRef = Page.REPLACE_NAME_OF_YOUR_VF_PAGE; //add name of your VF page
Test.setCurrentPage(pageRef);
        
        
        ApexPages.Standardcontroller sc = new ApexPages.Standardcontroller(obj);
	ApexPages.currentPage().getParameters().put('AccountId',obj.Credit_Account__c);
	ApexPages.currentPage().getParameters().put('OrderId',obj.Related_Order__c);

        
        CreditExtension ec = new CreditExtension (sc);
    } 
}

Please mark this as Best Answer if it helps you! ..
Jason DunphyJason Dunphy
Hi Saurabh,

Thanks for your quick reply.  I modified your suggestion slightly, as the name value for this object is auto-generated.
 
@isTest
public class thecontrollerTests {

    public static testMethod void testMyController() {
         Cust_Credit__c obj = new Cust_Credit__c();
         insert obj;

PageReference pageRef = Page.Credit_Memo_Entry
Test.setCurrentPage(pageRef);
        
        
        ApexPages.Standardcontroller sc = new ApexPages.Standardcontroller(obj);
	ApexPages.currentPage().getParameters().put('AccountId',obj.Credit_Account__c);
	ApexPages.currentPage().getParameters().put('OrderId',obj.Related_Order__c);

        
        CreditExtension ec = new CreditExtension (sc);
    } 
}

 With the unit test bit noted above, I received a full failure with the follow reason:

System.DmlException: Insert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [Credit_Memo_Account__c]: [Credit_Memo_Account__c]

I tried changing the unit test to put exact record ids for both the AccountId and OrderId, but received the same error message.  Any ideas what I'm still doing wrong?

Thanks again for your help with this.
Amit Chaudhary 8Amit Chaudhary 8
Please add all required field for test data
@isTest
public class thecontrollerTests {

    public static testMethod void testMyController() 
	{
		Account acc = new Account();
		acc.Name ='Test';
		insert acc;	
		
         Cust_Credit__c obj = new Cust_Credit__c();
		 obj.Credit_Memo_Account__c = acc.id;
		 // Please add all required field here
         insert obj;

		PageReference pageRef = Page.Credit_Memo_Entry
		Test.setCurrentPage(pageRef);
        
        
        ApexPages.Standardcontroller sc = new ApexPages.Standardcontroller(obj);
		ApexPages.currentPage().getParameters().put('AccountId',obj.Credit_Account__c);
		ApexPages.currentPage().getParameters().put('OrderId',obj.Related_Order__c);

        
        CreditExtension ec = new CreditExtension (sc);
    } 
}

 
Jason DunphyJason Dunphy
@isTest
public class creditMemoTest {

    public static testMethod void testMyController() 
    {
        Account acc = new Account();
        acc.Name ='Test Account';
        insert acc; 
        
       Cust_Credit__c obj = new Cust_Credit__c ();
         obj.Credit_Memo_Account__c = acc.id;
         obj.Credit_Amount__c = 200.00;

         insert obj;

        PageReference pageRef = Page.Credit_Memo_Entry;
        Test.setCurrentPage(pageRef);
        
        
        ApexPages.Standardcontroller sc = new ApexPages.Standardcontroller(obj);
        ApexPages.currentPage().getParameters().put('AccountId',obj.Credit_Memo_Account__c);
        ApexPages.currentPage().getParameters().put('OrderId',obj.Related_Order__c);

        
        CreditExtension ec = new CreditExtension (sc);
    } 
}
Hi Amit,

Thanks for your suggestion.  

I added the above per your suggestion, I really only have two mandatory fields on the object right now (account id and an amount (decimal).

When I run the test I get the following error.  This field is a master detail type.

System.SObjectException: Field is not writeable: Customer_Credit_Memo__c.Credit_Memo_Account__c
Saurabh BSaurabh B
Jason, I tried this in my Dev org and it appears to work fine.

A few questios -
Customer_Credit_Memo__c - is this another object in your org?
Credit_Memo_Account__c - which object is this field related to? Also, is this a formula fields ? Usually, formula fields are not writeable
Jason DunphyJason Dunphy
Hi Suarabh,

Customer_Credit_Memo__c was just copy and paste mistake on my part from my last post, should have been Cust_Credit__c.  And the Cust_Credit__c.Credit_Memo_Account__c field is a master detail field connecting the Cust_Credit__c object to  a standard Account object.

Full error is:
System.SObjectException: Field is not writeable: Cust_Credit__c.Credit_Memo_Account__c
Class.CreditExtension.<init>: line 6, column 1
Class.creditMemoTest.testMyController: line 25, column 1

Is it possible to pull acct info from an existing account for this unit test, or is that not best practice?  I'm sure it's something that I'm just simply overlooking.

Thanks again for helping me out here, I really appriciate it.
Saurabh BSaurabh B
Hi Jason, please try below and let me know if it works ...
 
@isTest
public class creditMemoTest {

    public static testMethod void testMyController() 
    {
        Account acc = new Account();
        acc.Name ='Test Account';
        insert acc; 
        
       Cust_Credit__c obj = new Cust_Credit__c (Credit_Memo_Account__c =acc.id);
         obj.Credit_Amount__c = 200.00;
         insert obj;

        PageReference pageRef = Page.Credit_Memo_Entry;
        Test.setCurrentPage(pageRef);
        
        
        ApexPages.Standardcontroller sc = new ApexPages.Standardcontroller(obj);
        ApexPages.currentPage().getParameters().put('AccountId',obj.Credit_Memo_Account__c);
        ApexPages.currentPage().getParameters().put('OrderId',obj.Related_Order__c);

        
        CreditExtension ec = new CreditExtension (sc);
    } 
}

If it still doesnt work, go to your Master-Detail field and try enabling "Allow Reparenting" option and try running test again.
This was selected as the best answer
Jason DunphyJason Dunphy
@isTest
public class creditMemoTest {

    public static testMethod void testMyController() 
    {
        Account acc = new Account();
        acc.Name ='Test Account';
        insert acc; 
        
       Cust_Credit__c obj = new Cust_Credit__c (Credit_Memo_Account__c =acc.id);
         obj.Credit_Amount__c = 200.00;
         insert obj;

        PageReference pageRef = Page.Credit_Memo_Entry;
        Test.setCurrentPage(pageRef);
        
        
        ApexPages.Standardcontroller sc = new ApexPages.Standardcontroller(obj);
        ApexPages.currentPage().getParameters().put('AccountId',obj.Credit_Memo_Account__c);
        ApexPages.currentPage().getParameters().put('OrderId',obj.Related_Order__c);

        
        CreditExtension ec = new CreditExtension (sc);
    } 
}
Hi Suarabh,

Your last suggestion plus 'allowing reparenting' for Credit_Memo_Account__C did the trick. Thank you so much!
 
Saurabh BSaurabh B
You are welcome! :)