+ Start a Discussion
Developer.mikie.Apex.StudentDeveloper.mikie.Apex.Student 

Help with test code for extension and question about extensions

Hey, was wondering if I could get a hand on writing a test for my extension below V. I also had a question: This extension is for the save button and re-directs to my VF page which a tabbed account view. I will have to write several extensions for each of the custom object tabs...is it possible to write one super extension which will re-direct all of them upon saving to my VF page?

 

public class extSaveButton {
 
    public Fact_Finder__c fac {get;set;}
    public extSaveButton(ApexPages.StandardController controller) {
        this.fac = (Fact_Finder__C)controller.getRecord();

    }
    
    Public PageReference saveFactFinder(){
    
        insert fac;
        // Send the user to the detail page for the new account.
       PageReference pageRef= new PageReference('/apex/DestinyAccountTest?id='+fac.account__c+'&Sfdc.override=1');
        pageRef.getParameters().put('tab','FactFinder');
        return pageRef;
    
    }

}

 

 

Best Answer chosen by Admin (Salesforce Developers) 
ericmonteericmonte

if it it is simple extension I usually create a simple testMethod at the end of the class. If the extension is being used in different class, then I usually would just create one big class testMethod that runs hits all classes and extensions.

 

To help with your extension test here is a simple testMethod you can use:

 

public class extButton {
    public Contact c{get;set;}

    public extButton(ApexPages.StandardController controller) {
        this.c = (Contact)controller.getRecord();

    }
    
    Public PageReference saveFactFinder(){
    
        insert c;
        
        PageReference pageRef = new PageReference('/003');
        
        return pageRef;
        
    }
    
    static testMethod void testExtension(){
    	
    	Contact cTest = new Contact(FirstName = 'Test', LastName = 'Test');
    	
    	
    	Apexpages.Standardcontroller stdCon = new Apexpages.Standardcontroller(cTest);
      	extButton ext = new extButton(stdCon);
      	ext.saveFactFinder();
    }
    
}

 Hope this helps.

All Answers

ericmonteericmonte

if it it is simple extension I usually create a simple testMethod at the end of the class. If the extension is being used in different class, then I usually would just create one big class testMethod that runs hits all classes and extensions.

 

To help with your extension test here is a simple testMethod you can use:

 

public class extButton {
    public Contact c{get;set;}

    public extButton(ApexPages.StandardController controller) {
        this.c = (Contact)controller.getRecord();

    }
    
    Public PageReference saveFactFinder(){
    
        insert c;
        
        PageReference pageRef = new PageReference('/003');
        
        return pageRef;
        
    }
    
    static testMethod void testExtension(){
    	
    	Contact cTest = new Contact(FirstName = 'Test', LastName = 'Test');
    	
    	
    	Apexpages.Standardcontroller stdCon = new Apexpages.Standardcontroller(cTest);
      	extButton ext = new extButton(stdCon);
      	ext.saveFactFinder();
    }
    
}

 Hope this helps.

This was selected as the best answer
Developer.mikie.Apex.StudentDeveloper.mikie.Apex.Student

I have tried using test code...but when I tried to make a class with the code that you psoted...I got an error:

 

Error: Compile Error: Test methods must be in test classes at line 19 column 28

Developer.mikie.Apex.StudentDeveloper.mikie.Apex.Student

What I mean is...say I have many custom objects which re-direct to new record VF pages. Upon clicking saving, do I have to write an extension for every object so that it will re-direct to the open tab or can I use the one I just posted as an extension for all my new record pages and simply add to them?

ericmonteericmonte
Can you please copy your code?

So when doing unit testing on the codes, you want to cover to try to reach to 100% code coverage in your class. How are you using the redirect in other VF pages? Are you just referring it based on one extension or are you creating multiple extensions with the same method? If you are reusing this extension then you would only need to cover code coverage for this extension. An example would be you have 5 different VF pages that have the same extension, therefore you would only have 1 extension and would only cover that class. But if you are using multiple extension with similar methods, then you would have to cover those code coverage for each class extension. For example, if you have 3 different VF pages, and 3 different extension with the same method of redirecting, then you would have to run a test coverage for all those classess separatey. I hope this make sense.
Developer.mikie.Apex.StudentDeveloper.mikie.Apex.Student

Basically I just copy and pasted your code into a new apex class and then I changed all the c's -> f's, all the cons to facs and all the contact into fact_finder__c.

 

The way it works is I have my main account VF tabbed page, the detail page is the information on the account and then each other tab is set up as a  custom or standard object that is a child to account with apageblocktable of the records with commandlinks re-rendering the bottom half of each tab for the records. There is a new record button that I have placed above the pageblocks which re-directs to a custom VF new record page...This new record page has the extsavebutton as an extension....it re-directs as shown above using the VF page url and the account id gotten through the custom object it is creating the new record for and the rest of the URL which is about overiding I beleive... I hope this makes sense? 

 

Thank you so much for your time eric.

ericmonteericmonte
I see. The code I gave earlier, you can add that as a regular method in your extension. If you put this code to a separate class you will have to use a different way to call the test. Let me see if I can dig the document for on writing unit test.
Developer.mikie.Apex.StudentDeveloper.mikie.Apex.Student

Still getting the error....I wonder why its not allowing me to just add it to the extension...Test methods msut be in test classes..what does that mean?

Developer.mikie.Apex.StudentDeveloper.mikie.Apex.Student

I wrote this...but I am pretty sure that I did it wrong..

 

 

@isTest
private class TestExtSaveButton {

 static testMethod void TestExtSaveButton(){
        
        Fact_Finder__c facTest = new Fact_Finder__c(Account__c = 'TestExtension');
        
        
        Apexpages.Standardcontroller stdFac = new Apexpages.Standardcontroller(facTest);
        extSaveButton ext = new extSaveButton(stdFac);
        ext.saveFactFinder();
    }
    
    }

ericmonteericmonte
public class extSaveButton {
 
    public Fact_Finder__c fac {get;set;}
    public extSaveButton(ApexPages.StandardController controller) {
        this.fac = (Fact_Finder__C)controller.getRecord();

    }
    
    Public PageReference saveFactFinder(){
    
        insert fac;
        // Send the user to the detail page for the new account.
       PageReference pageRef= new PageReference('/apex/DestinyAccountTest?id='+fac.account__c+'&Sfdc.override=1');
        pageRef.getParameters().put('tab','FactFinder');
        return pageRef;
    
    }

//create a testMethod within in your extension

static testMethod void TestExtSaveButton(){
        //Based on your code and what you give me, Fact Finder is a child of the Account and when you //attach fact finder it needs to be reference into an account.

// create a test account that will be use to reference the Fact Finder Record

Account acc = new Account(Name = 'Test Account');
insert acc;

//Now lets create Fact Finder record that will be reference for the Standard Account
        Fact_Finder__c facTest = new Fact_Finder__c(Account__c = acc.id);
        
        //call the apepages stad controller
        Apexpages.Standardcontroller stdFac = new Apexpages.Standardcontroller(facTest);

//now call the class and reference the standardcontroller in the class.
        extSaveButton ext = new extSaveButton(stdFac);

//call the pageReference in the class.
        ext.saveFactFinder();
    }

}

 All right i managed to recreate your whole structure in my environment and this should work. So in your current extension append all that stuff.

 

Also, please take a look at this on how to write a good unit test:

 

http://wiki.developerforce.com/page/How_to_Write_Good_Unit_Tests

 

Let me know if the code works out for you.

Developer.mikie.Apex.StudentDeveloper.mikie.Apex.Student

Figured it out, Thank you sooo much for your help. 

 

This was the end code, essentially your code but changed to be in its own class.

 

@isTest
private class TestExtSaveButton {
static testMethod void TestExtSaveButton(){      
Fact_Finder__c facTest = new Fact_Finder__c(Account__c = '001N000000819na');
Apexpages.Standardcontroller stdCon = new Apexpages.Standardcontroller(facTest);
extSaveButton ext = new extSaveButton(stdCon);
ext.saveFactFinder();
}
}

 So, will I have to create a separate extension for every new record re-direction or can I add to the extensiona bove and use it for a few (if they are all re-directing to the same page?

Developer.mikie.Apex.StudentDeveloper.mikie.Apex.Student

I gave your thing a try and it still says that test methods must be in test classes...I read something a few minutes ago about a change in a recent update that makes it so that test classes must be in their own class....could this be why, or have you used it like this recently?

ericmonteericmonte

Yea I'm using this now and the code is sitting on my dev winter 14 sandbox. Not sure why it;s not working but glad you were able to figure it out.

 

And to answer your question, you can have 1 class to house all your testMethod and they can be almost the same format except changing the Custom Object. The reason for this is because you are creating multiple extension classes and you need to basically run a test scenario to hit those classes. So essentially your class method will look somehting like this:

 

 

@isTest
private class TestExtSaveButton {
static testMethod void TestExtSaveButton(){      
Fact_Finder__c facTest = new Fact_Finder__c(Account__c = '001N000000819na');
Apexpages.Standardcontroller stdCon = new Apexpages.Standardcontroller(facTest);
extSaveButton ext = new extSaveButton(stdCon);
ext.saveFactFinder();
}

static testMethod void TestExtSaveButton2(){
.... referencing the other extension and changing Fact Finder to a new Custom Object
}

static testMethod void testExtSaveButton3(){
... referencing another extension and changing the Fact Finder to a new custom Object
}


}
Developer.mikie.Apex.StudentDeveloper.mikie.Apex.Student

New code after reviewing your suggestions. This way I w8ill not have to change the ID to one from my production when porting it over. Thank you mate, you have really helped me. This is final test class:

 

@isTest
private class TestExtSaveButton {

static testMethod void TestExtSaveButton(){
        //Based on your code and what you give me, Fact Finder is a child of the Account and when you //attach fact finder it needs to be reference into an account.

// create a test account that will be use to reference the Fact Finder Record

Account acc = new Account(Name = 'Test Account');
insert acc;

//Now lets create Fact Finder record that will be reference for the Standard Account
        Fact_Finder__c facTest = new Fact_Finder__c(Account__c = acc.id);
        
        //call the apepages stad controller
        Apexpages.Standardcontroller stdFac = new Apexpages.Standardcontroller(facTest);

//now call the class and reference the standardcontroller in the class.
        extSaveButton ext = new extSaveButton(stdFac);

//call the pageReference in the class.
        ext.saveFactFinder();
    }

}

Developer.mikie.Apex.StudentDeveloper.mikie.Apex.Student

So you can make one super test method for all the Testclasses...except you cant make one super extension which will house all the different savebutton extensions? Is that right?

ericmonteericmonte

Awesome bud... and you are right my stupid api was runnin on version 26 therefore it didn't error out. Okay i will put a big NOTE to myself next time when writing class to just use a seperate class.

 

And as for hard coding Ids, never like the idea and when i started with SFDC and testing i used to hard code a lot of values in sandbox and when i pushed it out to prod everything breaks. So now i never hardcode anything and when I do hard code i use custom labels and custom settings.

 

Glad i can help out.

ericmonteericmonte

Yes, you can create one big TestClass but you cant create one test for all your extension unless you create a dynamic visualforce page and controller. That is another topic that you might want to look into, but it takes a lot of work and understanding all the dynamic controller stuff.

Developer.mikie.Apex.StudentDeveloper.mikie.Apex.Student

k, thank you for your time Eric. I really appreciate it you legend.

Developer.mikie.Apex.StudentDeveloper.mikie.Apex.Student

So sorry to bother you again buddy...but I was wondering if you could give me a hand with writing a test for my attachmentAccount extension...I can only get 52%. Don't feel obligated, only if you have time.

 

Test:

@istest

private class TestAccountExtension{

static testMethod void TestAccountExtension() {
Account acc = new Account(Name = 'Test Att Account');
insert acc;
Attachment attachment = new Attachment();
attachment.Name = 'Unit Test Attachment';
attachment.Body = Blob.valueOf('Unit Test Attachment Body');
attachment.parentId = acc.id;
Insert attachment;


//Create the controller
ApexPages.StandardController sc = new ApexPages.StandardController(acc);

//Create the instances of the controller
AccountExtension myPageTest = new AccountExtension();

AccountExtension myPageTestSC = new AccountExtension(sc);
myPageTestSC.save();
}
}

 

 

Extension:

 

public class AccountExtension
{
private final Account webAccount;
public AccountExtension(ApexPages.StandardController stdController)
{
webAccount = (Account)stdController.getRecord();
attach = new Attachment();
}


public AccountExtension(){}
public PageReference saveAccount()
{
PageReference p= new PageReference('/apex/DestinyAccount?id='+webAccount.Id+'&sfdc.override=1');
p.setRedirect(true);
p.getParameters().put('tab','Attachments');
return p;
}
public PageReference save()
{
 PageReference p= new PageReference('/apex/DestinyAccount?id='+webAccount.Id+'&sfdc.override=1');
p.setRedirect(true);
p.getParameters().put('tab','Attachments');
update webAccount;
upload();
return p;
}
public String parentId {get;set;}
public Attachment attach {get;set;}
public ApexPages.Pagereference upload()
{
attach.ParentId = webAccount.Id;
insert attach;
return new ApexPages.Standardcontroller(attach).view();
}

}

 Thank you in advance

ericmonteericmonte

You almost got it try this:

 

@istest

private class TestAccountExtension{

static testMethod void TestAccountExtension() {
Account acc = new Account(Name = 'Test Att Account');
insert acc;
Attachment attachment = new Attachment();
attachment.Name = 'Unit Test Attachment';
attachment.Body = Blob.valueOf('Unit Test Attachment Body');
attachment.parentId = acc.id;
Insert attachment;


//Create the controller
ApexPages.StandardController sc = new ApexPages.StandardController(acc);

//Create the instances of the controller
AccountExtension myPageTest = new AccountExtension();

AccountExtension myPageTestSC = new AccountExtension(sc);
myPageTestSC.save();

//you didnt account for saveAccount pageReference add this
myPageTestSC.saveAccount();
}
}

 

Developer.mikie.Apex.StudentDeveloper.mikie.Apex.Student

It still failed. but we are up to 69% coverage. These were the errors: 

 

(Is it telling me that I need to change something inside the actual class (twice) and once inside the test class?

 

Error Message System.DmlException: Insert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [Name, Body]: [Name, Body] Stack Trace Class.AccountExtension.upload: line 33, column 1
Class.AccountExtension.save: line 25, column 1
Class.TestAccountExtension.TestAccountExtension: line 22, column 1

ericmonteericmonte

You know what i just realized, I can't seem to understand what you are trying to do in the code using the attachment. I should have read the code thoroughly.

 

Do you think you can paste VF page where you upload the attachment?

 

ericmonteericmonte

So i have to tell you how much i hate writing unit test for Attachments. Anyway's based on your code I kind of tried to tweak it, so here it

 

public class AccountExtension{
    public Account webAccount{get;set;}
	public AccountExtension(ApexPages.StandardController stdController){
	this.webAccount = (Account)stdController.getRecord();
	//attach = new Attachment();
    }
    
    public Attachment attach = new Attachment();
    public Blob bl {get; set;} 
    public String contentType {get; set;} 
    public String fileName {get; set;}
    
    public PageReference upload(){
        attach.OwnerId = UserInfo.getUserId();
        attach.ParentId = webAccount.Id;
        attach.Name = fileName;
        attach.Body = bl;
        attach.ContentType = contentType;
        
        insert attach;
        /*try {
      		insert attach;
    	} catch (DMLException e) {
     		ApexPages.addMessage(new ApexPages.message(ApexPages.severity.ERROR,'Error uploading attachment'));
      	return null;
    	} finally {
      	attach = new Attachment(); 
    	}*/
        
        PageReference p= new PageReference('/apex/DestinyAccount?id='+webAccount.Id+'&sfdc.override=1');
        p.setRedirect(true);
        p.getParameters().put('tab','Attachments');
        return p;
    }
}

 

@isTest
public class AttachTest{
    static testMethod void testAttachments(){
    	Account acc = new Account (Name ='TEST DEBUG');
        insert acc;
        
        
        
        AccountExtension controller = new AccountExtension(new ApexPages.standardController(acc));
        Attachment attach=new Attachment();
        attach.Name='Unit Test Attachment';
    	attach.Body=Blob.valueOf('Unit Test Attachment Body');
        attach.ParentId = acc.id;
        insert attach;
        
        controller.bl=Blob.valueof('Unit test blob');
		controller.contentType='text/plain';
		controller.fileName='UnitTest.txt';
        controller.upload();
        

        
        
        
    }
    
}

 I was able to run this code and test it and i got 100%. So hopefully this helps.

Developer.mikie.Apex.StudentDeveloper.mikie.Apex.Student

I really appreciate your help then. When i tried to change the extension to the new one on the VF page it said:

 


Error: Unknown property 'AccountStandardController.attach'

 

What could that mean. The reference for attach is in the new extension aswell isnt it?

Developer.mikie.Apex.StudentDeveloper.mikie.Apex.Student

Here is the VF code, sorry for the late reply..only just read that bit.

 

<apex:tab label="Attachments"
name="Attachments" id="tabAttachments"  >
<apex:form >
<apex:pageBlock title="Attachment" mode="edit">
<apex:pageBlockButtons >
<apex:commandButton value="Save"
action="{!save}"/>
</apex:pageBlockButtons>
<apex:pageBlockSection collapsible="false"
columns="1" >
<apex:inputHidden value="{!account.Name}"/>
<apex:outputText value="Attachment: "/><apex:inputFile value="{!attach.body}" filename="{!attach.name}"/><br/>
</apex:pageBlockSection>
</apex:pageBlock>
</apex:form>

 It is a tab in an accounts VF page where the user can save an attachment and then the reads the tab paramaters and reloads to the same attachments tab. I hope this helps.

Developer.mikie.Apex.StudentDeveloper.mikie.Apex.Student

Your code tested 100%, except my VF page will not accept it because of an unknown property accountstandardcontroller.attach. Basically, the controller originally was there as a way in which a user would attach an attachment to an account. The functionality was then added to re-direct the user back to the VF page (after saving), then further functionality was added to re-direct to the attachments tab....Something weird just happened, I have done it a thousand times and a thousand times it had worked, but randomly when attempting to save an attachment today....it re-directed to the details tab and the attachments tab was no longer visible.....quite wierd, what do you think might be the reason?

Developer.mikie.Apex.StudentDeveloper.mikie.Apex.Student

Sorry, how embarassing, I changed the pageref to one of my other VF pages which is identical asides from the attachments tab. But for some reason the page will still not recognize property 'AccountStandardController.attach'.

Developer.mikie.Apex.StudentDeveloper.mikie.Apex.Student

Got it buddy, for some reason the new extension would not add to the VF page..it was not recognizing the attach variable for some reason...Either way, the original test code that you helped me fix up worked like a charm..I just had to add this line to my extension:

 

attach.Name = 'Unit Test Attachment';
attach.Body = Blob.valueOf('Unit Test Attachment Body');

 

Thank you so much for your time and help. Such a legend.

ericmonteericmonte

your welcome buddy... 

Developer.mikie.Apex.StudentDeveloper.mikie.Apex.Student

Ended up using the second code and test afterall. When I added those lines to the extension, although it would pass 100%. When i was adding attachments it would always ahve the name unit test.... I didnt use it before as Whenever i tried to change the extension over on the VF page I would get an error, I did not realise i had to change the filename and body to be the same as in the extension. Once again, thankyou my friend