2

I'm having trouble writing a test class for a custom controller used in an VF page. The goal is a UI allowing the creation of multiple records for a Custom Object Time_item__c. Everything works as expected, but I can't for the life of me figure out the test class.

The controller code:

public class AddmultipleTimeItemsController {
    Time_Item__c TimeItem = new Time_Item__c();
    public list<Time_Item__c> listTimeItem{ get; set; }

    public AddmultipleTimeItemsController(){
        listTimeItem=new list<Time_Item__c>();
        listTimeItem.add(TimeItem);
    }


    public void addTimeItem(){
        Time_Item__c TI = new Time_Item__c();
        listTimeItem.add(TI);
    }
    public PageReference saveTimeItem() {
        for(Integer i=0; i<listTimeItem.size(); i++) {
            upsert listTimeItem;
        }
        return Page.Alltimeitemssaved;
    }
}

The VF page:

<apex:page Controller="AddmultipleTimeItemsController">
     <apex:form >
           <apex:pageBlock >
                  <apex:pageBlockTable value="{!listTimeItem}" var="TI">
                        <apex:column headerValue="Account Name">
                                <apex:inputField value="{!TI.AccountTime__c}"/>
                        </apex:column>
                        <apex:column headerValue="Case Number">
                               <apex:inputField value="{!TI.CaseItem__c}"/>
                        </apex:column>
                        <apex:column headerValue="Type">
                              <apex:inputField value="{!TI.TypeTime__c}"/>
                        </apex:column>
                        <apex:column headerValue="Hours">
                              <apex:inputField value="{!TI.Hours__c}"/>
                        </apex:column>
                        <apex:column headerValue="Notes">
                             <apex:inputField value="{!TI.Notes__c}"/>
                        </apex:column>
                 </apex:pageBlockTable>
                 <apex:pageBlockButtons >
                       <apex:commandButton value="Add Time Item Row" action="{!addTimeItem}"/>
                       <apex:commandButton value="Save Time Items" action="{!saveTimeItem}"/>
                 </apex:pageBlockButtons>
           </apex:pageBlock>
     </apex:form>
</apex:page>

I'm relatively new to coding in general, so any help is greatly appreciated.

Edit: My attempt at adapting an example test class

@isTest
public class addMultpleTestClass {

    public static testMethod void testMyController() {
        //PageReference pageRef = Page.Alltimeitemssaved;
       // Test.setCurrentPage(pageRef);

       AddmultipleTimeItemsController controller = new AddmultipleTimeItemsController();
        String nextPage = controller.saveTimeItem().getUrl();

        // Verify that page fails without parameters
        System.assertEquals('/apex/failure?error=noParam', nextPage);



        // Instantiate a new controller with all parameters in the page
       Account testAccount = new Account(name='Acc');
        insert testAccount;
        Time_Item__c TI = new Time_Item__c(Hours__c=5.00,AccountTime__c = testAccount.Id, TypeTime__c ='Pre-Sales' );
       // insert TI;
        controller = new AddmultipleTimeItemsController(); 
        controller.addTimeItem();
        nextPage = controller.saveTimeItem().getUrl();

        // Verify that the success page displays
        System.assertEquals('/apex/Alltimeitemssaved', nextPage);

    }
}

The test fails citing missing required fields (Hours__c and AccountTime__c).

Cheers!

| improve this question | | | | |
  • 2
    Welcome to SFSE. The community will be a great resource when you get stuck. However, you will not find a great reception for "Write it for me" type of questions. Plenty of places exist to get that done for you at a cost. If help is what you want, start at developer.force.com and follow the paths to learn the ins and outs. If you are stick with something you have written, please update your question. – Eric Jan 3 '15 at 22:32
  • 1
    Can you post what you have so far for test code and what issues / errors you are running into? – Jenny B Jan 3 '15 at 22:42
  • 1
    In general I find it helpful to create one test function for each condition of each controller method. Luckily for you that will be pretty much just a one to one mapping. There is at least one issue you need to address in your controller though - you are upsert-ing each time record independently when you can just upsert the whole list in one call. – Andrew Monshizadeh Jan 3 '15 at 22:52
  • Are the Hours__c and AccountTime__c fields required fields on the Time_Item__c object? If so, you will have to fill those values in before you can attempt to save. I'm guessing that if you leave those fields blank on your Visualforce page, you will get the same error when you attempt to save. – Andrew Monshizadeh Jan 4 '15 at 0:32
  • 1
    @ibury you will need to access the controller's records after you call the controller.addTimeItem() and update them by hand. Which is how the functionality behaves on the Visualforce page -- the user navigates to the page, adds a time record, then manually updates the values in the table, then clicks Save. In tests you need to simulate this behavior. This might be easiest to accomplish with a for (Time_Item__c ti : controller.listTimeItem) { c.Hours__c = 10; c.AccountTime__c = 42; } or the like. Please note, I do not know the actual field types, just guessing. – Andrew Monshizadeh Jan 4 '15 at 0:48
2

If you analyze the VF code, the two fields viz. Hours & AccountTime are really user input from the UI. So its important to mimic the same scenario in the context the code.

In the controller, you are adding rows in listTimeItem to perform an upsert and also if you observe your VF page the User input from UI is also bound with the same List listTimeItem. So in order to replicate this, you should be really adding blank rows using method addTimeItem(); Then iterate through the list listTimeItem to mimic user input by supplying values for the required fields. After the list is ready, use the saveTimeItem() method to try upserting the data. This is how your test class should look like :

@isTest
public class addMultpleTestClass {

    public static testMethod void testMyController() {
        PageReference pageRef = Page.Alltimeitemssaved;
        Test.setCurrentPage(pageRef);

        AddmultipleTimeItemsController controller = new AddmultipleTimeItemsController();
        String nextPage = controller.saveTimeItem().getUrl();

        // Verify that page fails without parameters
        System.assertEquals('/apex/failure?error=noParam', nextPage);



        // Instantiate a new controller with all parameters in the page
        Account testAccount = new Account(name='Acc');
        insert testAccount;
        controller = new AddmultipleTimeItemsController(); 
        controller.addTimeItem();
        controller.addTimeItem();
        controller.addTimeItem();
        for (Time_Item__c ti : controller.listTimeItem) {
            c.Hours__c = 10;
            c.AccountTime__c = testAccount.Id; 
            c.TypeTime__c ='Pre-Sales';
            c.Notes__c = 'sample Notes';
            c.CaseItem__c = *put relevant value over here*.
        }
        nextPage = controller.saveTimeItem().getUrl();

        // Verify that the success page displays
        System.assertEquals('/apex/Alltimeitemssaved', nextPage);

    }
}
| improve this answer | | | | |
  • 2
    even though this code may solve the problem, in my opinion you should add more explanation to your answer, especially since OP said that he is relatively new to coding – Novarg Jan 5 '15 at 6:57
  • Agreed! thanks for the suggestion. Let me do that! – Amit Bangad Jan 5 '15 at 7:13

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.