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
mparramparra 

Unit Testing Controller Extensions


I'm getting an error in trying to write a Test method that will compile. I started with the sample test code from the VF Developer's Guide. Here's my code:
 

public class newIP_Extension{
    
     private
final IP__c ip;

     public newIP_Extension(ApexPages.StandardController stdController){
          this.ip = (IP__c)stdController.getRecord();
     }

     <SNIP - many methods>

     public static testMethod void test_newIP_Extension(){
          Test.setCurrentPageReference(new PageReference('Page.newIP'));

          newIP_Extension controller = new newIP_Extension('IP__c'); 
          String nextPage = controller.continueToNext().getUrl();

          <SNIP various tests>
     }

}

This is the error I get "Error: Compile Error: Constructor not defined: [newIP_Extension].<Constructor>(String) at line 148 column 38 ."

If I don't pass 'IP__c' (the name of the standard controller) into the constructor I get "Error: Compile Error: Constructor not defined: [newIP_Extension].<Constructor>() at line 148 column 38 ."

If I don't quote IP__c I get "Error: Compile Error: Variable does not exist: IP__c line 148 column 58. "

The only difference between my code and the sample code is that the sample code is for a custom controller (rather than extension) and thus the controller doesn't have any parameters. What am I missing here?

Thanks for any insights!

Best Answer chosen by Admin (Salesforce Developers) 
mtbclimbermtbclimber
Unfortunately we currently have a limitation that you are running into. Fortunately there is a workaround.

The limitation is that the standardController can not be constructed.

The workaround is to create a new constructor that takes an sobject like the one handed to your extension in the required constructor.  Then minimize the amount of logic in your constructor by factoring it out into a method that can be called from both constructors so you can cover as much code as possible with your test.

Here is a quick sample for you....

Code:
public class accountExt {


    Account a;
    
    public accountExt(Account a) {
      this.a = a;
      init();
    }


    public accountExt(ApexPages.StandardController controller) {
      a = (Account)controller.getRecord();
      init();
    }


    private void init() {}


    public String getName() { 
return a.name; } public static testMethod void accountExtTest() { AccountExt ext = new AccountExt(new Account(Name = 'Foo')); System.assertEquals('Foo',ext.getName()); } }

 


All Answers

mtbclimbermtbclimber
Unfortunately we currently have a limitation that you are running into. Fortunately there is a workaround.

The limitation is that the standardController can not be constructed.

The workaround is to create a new constructor that takes an sobject like the one handed to your extension in the required constructor.  Then minimize the amount of logic in your constructor by factoring it out into a method that can be called from both constructors so you can cover as much code as possible with your test.

Here is a quick sample for you....

Code:
public class accountExt {


    Account a;
    
    public accountExt(Account a) {
      this.a = a;
      init();
    }


    public accountExt(ApexPages.StandardController controller) {
      a = (Account)controller.getRecord();
      init();
    }


    private void init() {}


    public String getName() { 
return a.name; } public static testMethod void accountExtTest() { AccountExt ext = new AccountExt(new Account(Name = 'Foo')); System.assertEquals('Foo',ext.getName()); } }

 


This was selected as the best answer
samdsamd
I was running into the same issue trying to construct an instance of a standardController.  I re-worked the extension constructor as suggested, but I need to make use of the standardController save() function as shown below:

Code:
public class VfExt_LeadTaskExtension{

private ApexPages.StandardController m_StdController;
private Task m_Task;

public VfExt_LeadTaskExtension(Task LeadTask) {
// Get instance of standard Task controller
this.m_Task = LeadTask;
Init();
}

public VfExt_LeadTaskExtension(ApexPages.StandardController controller) {
// Get instance of standard Task controller
m_StdController = controller;
// Get instance of current task
this.m_Task = (Task)m_StdController.getRecord();
Init();
}

public void Init()
{
Task TempTask = [select WhoId,OwnerId,ActivityDate from Task where Task.Id = :this.m_Task.Id][0];
this.m_Task.WhoId = TempTask.WhoId;
this.m_Task.ActivityDate = TempTask.ActivityDate;
this.m_OriginalOwnerId = TempTask.OwnerId;
}

public PageReference SaveAndUpdateStatus()
{
// Set task status to "Closed - No Opportunity" due to user
// rejecting the lead
this.m_Task.Status = 'Closed - No Opportunity';
m_StdController.save();
// Return the user to the contact details page
Task TempTask = [select WhoId from Task where Task.Id = :this.m_Task.Id][0];
PageReference contactPage= new PageReference('/' + TempTask.WhoId);
contactPage.setRedirect(true);
return contactPage;

}
}

 If I can't create an instance of a standardController, how can I execute this code in a test method?

Many thanks
Sam

mtbclimbermtbclimber
BTW, the limitation has been addressed. You can construct a standardcontroller now like this:

Code:
ApexPages.StandardController controller = new ApexPages.StandardController(new Task());

 Of course if you already have a task, don't create a new one ;-)

samdsamd
Hi

Many thanks for the quick response. I have reworked the code (back to how I had it before I found this post ;)) and I'm now getting the same internal server error that originally I thought was being cause by the standardController constructor issue (the error occurs when I run the tests).  My testmethod is below, the error page is beneath that.

Code:
    public static testMethod void testVfExt_LeadTaskExtension() {        
Contact NewContact = new Contact();
NewContact.FirstName = 'Joe';
NewContact.LastName = 'Soap';
insert NewContact;
Campaign NewCampaign = new Campaign(Name='Test Campaign');
insert NewCampaign;
Campaign TestCampaign = [select Id from Campaign where Id = :NewCampaign.Id][0];
Contact TestContact = [select Id from Contact where Id = :NewContact.Id][0];
Task NewLeadTask = new Task();
NewLeadTask.WhoId = TestContact.Id;
NewLeadTask.WhatId = TestCampaign.Id;
NewLeadTask.Subject = 'Test Lead Task';
Id RecordTypeId = [select Id from RecordType where Name = 'Lead Follow Up'][0].Id;
NewLeadTask.RecordTypeId = RecordTypeId;
insert NewLeadTask;
Task TestLeadTask = [select Id from Task where Id =:NewLeadTask.Id][0];
ApexPages.StandardController stc = new ApexPages.StandardController(TestLeadTask);
Test.startTest();
VfExt_LeadTaskExtension TestExtension = new VfExt_LeadTaskExtension(stc);
TestExtension.SaveAndUpdateStatus();
Test.stopTest();
}

 
Code:
An internal server error has occurred
An error has occurred while processing your request. The salesforce.com support team has been notified of the problem. If you believe you have additional information that may be of help in reproducing or correcting the error, please contact support@salesforce.com. Please indicate the URL of the page you were requesting, any error id shown on this page as well as any other related information. We apologize for the inconvenience.

Thank you again for your patience and assistance. And thanks for using Salesforce!

Error ID: 1464304895-1223 (-1557452464) 

It seems that the error is caused by the TestExtension.SaveAndUpdateStatus() function call (shown in red above).  If I comment this out, the tests run with no failures.


Many thanks in advance

Sam



Message Edited by samd on 07-25-2008 03:50 AM

Message Edited by samd on 07-25-2008 03:55 AM
samdsamd
Any ideas on what's causing the internal server error?  I'm going to need to migrate the code to our production environment in the next few days and this is a bit of show stopper!

Many thanks
Sam
samdsamd
After contacting SFDC Premier Support, the error appears to have been resolved or was due to some system issue at the time I was running the tests.

Sam