3

Ok, I am confused as to why I am not getting a list returned back to me.

The error I am getting is:

System.ListException: List index out of bounds: 0

However, I know that means that there is nothing in that list to reference, but why? I am getting the error after I have already run a similar method in a test where I am manipulating the boolean, and it is written very similar. Anyways the error is at this line: RegCon.courseList[0].checkedCourses=true;

The code is working just fine when I am running it, but in my test method, I am not getting a return on this list. After 3 days of looking at this, I think I need a fresh set of eyes. Thank you all in advance, and sorry for so much code, you cant follow it without it. Oh, and if it is ugly and you want to give me advice, feel free to do so, this is my first time writing code in apex though, so be easy on me please.

Controller:

public class RegistrationController {
            //Variables
            public list <account> acc {get;set;}
            public string searchstring {get;set;}
            public string stuId;
            public boolean boolPE = False;

       //Create a map of courses
        //Map<Id, Course__c> coursesMap = new Map<Id, Course__c>();

        // Container/Wrapper
        public list<cProgramEnrollment> peList {get; set;}
        public list<cCourse> courseList {get; set;}
        public list<cProgramAtt> programAttWrap {get; set;}

        //New list of Courses 'selectedCourses' - to be populated only with courses if they are selected
        public List<Course__c> selectedCourses = new List<Course__c>();

        //New list of Program enrollments 'selectedPE' - to be populated only with program enrollments if they are selected
        public List<Program_Enrollment__c> selectedPE = new List<Program_Enrollment__c>();

        //New list of Program attachments 'programAtt' - to be populated with selectedPE.Programs__c
        public List<Program_Attachment__c> programAtt = new List<Program_Attachment__c>();

        // The wrapper/container class for Program Entrollments. - used to allow students to choose programs from the returned PE from attached stuId
            public class cProgramEnrollment {
                    public Program_Enrollment__c PE {get; set;}
                    public Boolean checkedPE {get; set;}

                    //Contructor method.
                    public cProgramEnrollment(Program_Enrollment__c pen) {
                            PE = pen;
                            checkedPE = false;
                    }
            }

          // The wrapper/container class for Program. - used to get program out of Program Enrollments, needed to be able to get courses. 
            public class cProgramAtt {
                    public Program_Attachment__c PA {get; set;}

                    //Contructor method.
                    public cProgramAtt(Program_Attachment__c pat) {
                            PA = pat;
                    }
            }

              // The wrapper/container class for courses.  A container class is a class, a data structure, or an abstract data type whose instances are collections of other objects.
            public class cCourse {
                    public Course__c cou {get; set;}
                    public Boolean checkedCourses {get; set;}

                    //This is the contructor method. When we create a new cCourse object we pass a Course__c that is set to the cou property.
                    //We also set the selected value to false
                    public cCourse(Course__c c) {
                            cou = c;
                            checkedCourses = false;
                    }
            }


        // 'Search' method -    
       public void search(){
           // added if for security, prevent null searches
           if(searchstring.length()>=8){
                   getId();
               //system.debug('stuId 1 is: ' + stuId);
           }
       }

         // Save student ID to variable 'stuId' - called by search
        public string getId(){
            try{  
                string searchQueryAcc='SELECT id,name,ufid__c,Program_Name__c,Program__c FROM account WHERE ufid__c like \'%'+searchstring+'%\' Limit 1';
                acc= Database.query(searchQueryAcc);
               //if statement for error handling null returns
               if(acc.size()>0){
                   stuId=acc[0].id;
                   searchstring = null;
                   //system.debug('stuId 0 is: ' + stuId);
                   boolPE = false;
                }
            }
            catch(exception e){}
            return stuId;
            searchstring = null;
            return searchstring;

        }


           // Wrapper for program enrollment 'getEnrolled' return 'peList'
            public List<cProgramEnrollment> getEnrolled() {
                    if(boolPE == false) {              //!!!!!!!!!!!!!!!!if with (peList == null) not working properly, need to check for null persistence. Using bool as workaround for now
                            peList = new List<cProgramEnrollment>();
                            for(Program_Enrollment__c pro : [SELECT Program__c
                                      FROM Program_Enrollment__c
                                      WHERE Student__c = :stuId]){
                                    // As each program enrollment is processed we create a new cProgramEnrollment object and add it to the peList
                                    peList.add(new cProgramEnrollment(pro));
                            }
                        boolPE = true;
                    }
                 /*  system.debug('"getEnrolled" called to return enrollments with stuId');
                   for (cProgramEnrollment pe: peList){
                        system.debug(pe);}   */
                return peList;
            }

        //VF step 2 !courses query to return a List of Courses 
            public List<cCourse> getCourses() {
                  /*if(courseList == null) {
                            courseList = new List<cCourse>();

                    //system.debug('"getCourses print courseList" :');
                    //for(cCourse c: courseList) {
                    //        system.debug(c);
                    //}
                  } */
                    //courseList.sort();
                    return courseList;    
            }


        // method to retrieve selected programs
        public List<Program_Enrollment__c> getselectedPE(){
            /*  testing
            system.debug('!selectedPE');
            for(Program_Enrollment__c programs: selectedPE) {
                            system.debug(programs);} */

            if(selectedPE.size()>0)
              return selectedPE;
            else
              return null;
        }  

          //VF step 2 !getProAtt query to return a List of Courses 
            public List<Program_Attachment__c> getProAtt() {
                    return programAtt;              
            }

        // method to retrieve selected accounts for confirmation
        public List<Course__c> getselectedCourses()
        {
            if(selectedCourses.size()>0)
              return selectedCourses;
            else
              return null;
        }  

        // Cancels the wizard, and returns the user to the step 1 of registration
       public PageReference cancel() {
          PageReference StudentRegistration = new PageReference('https://cs21.salesforce.com/apex/StudentRegistration');
              StudentRegistration.setRedirect(true);
              return StudentRegistration;
       }

        //Used for next button on /apex/StudentRegistration
       public PageReference step1() {
             // added if for security and to avoid null reference points
             if(stuid != null){

        //Cycle through list of cProgramEnrollment, if checkedPe set to true,  add the Course to the selectPE list
                    for(cProgramEnrollment cPE: getEnrolled()) {
                            if(cPE.checkedPE == true) {
                                    selectedPE.add(cPE.PE);
                            }
                    }

         // take selectedPE and get program attachments where program__c matches selected from program enrollments.
                          //System.debug('At selected program enrollments, iterate selectPE to get program_attachments ..');
                         //integer peCount = selectedPE.size();
                    programAttWrap = new List<cProgramAtt>();
                    for(Program_Enrollment__c pe : selectedPE) {
                           // system.debug('peCount = ' + peCount);
                           // system.debug(pe);
                           // system.debug(pe.Program__c);
                         //if (pe != null)

                             for(Program_Attachment__c p : [SELECT Id, Program__c, Course__c, Type__c FROM Program_Attachment__c  WHERE Program__c = : pe.program__c]){
                                    // As each program enrollment is processed we create a new cProgramAtt object and add it to the programAttWrap
                             programAttWrap.add(new cProgramAtt(p));}

                    }

           //Cycle through list of programAttWrap,  add to the progAtt list to be able to work with sObject
           if(programAttWrap != null){
                        for(cProgramAtt cPA: programAttWrap) {
                        if (cPA != null){
                                    programAtt.add(cPA.pa); 
                         }             
                    }
           }


           //integer patCount = programAtt.size();  
           courseList = new List<cCourse>();     
           for(Program_Attachment__c pa : programAtt) {
                 //system.debug('patCount = ' + patCount);
                 //system.debug(pa);
                 //system.debug(pa.Course__c);

                      for(Course__c y : [select ID, Name, Credits__c, Total_Price__c from Course__c Where Id = : pa.Course__c]) {
                                    // As each course is processed we create a new cCourse object and add it to the courseList
                         courseList.add(new cCourse(y)); }           
                            }                 

           /* System.debug('These are whats in courseList from programAtt...');
           if (courseList != null){
                    for(cCourse cours: courseList) {
                        system.debug(cours);}
           }  */
                    //coursePE=null; // need this line if we performed a write operation  because getEnrolled gets a fresh list now - testing


           return Page.StudentRegistrationStep2;
         }
           else       
              return null;
       }
        // used in next button in /apex/StudentRegistrationStep2
       public PageReference step2() {


                    //Cycle through list of cCourses, if checkedCourses set to true,  add the Course to the selectedCourses list
                    for(cCourse cCou: getCourses()) {
                            if(cCou.checkedCourses == true) {
                                    selectedCourses.add(cCou.cou);
                            }
                    }

                    // Now we have our list of selected courses and can perform any type of logic we want, sending emails, updating a field on the Contact, etc
                   /* System.debug('These are the selected Courses...');
                    for(Course__c courses: selectedCourses) {
                            system.debug(courses);  
                    }  */
                    //courseList=null; // we need this line if we performed a write operation  because getCourses gets a fresh list now
- testing
            return Page.StudentRegistrationStep3;
       }

          // Submit button in /apex/StudentRegistrationStep3. This method performs the final save for a new registration 
       public PageReference submit(){

           for(Course__c sub : selectedCourses){
          Registration_Request__c rr = new Registration_Request__c();
           rr.Student__c = stuId;
           rr.Course__c = (sub.Id);
          insert rr;

           }      
           return page.StudentRegistrationThankYou;
       } 
    }

Test class: *note, I am only posting the method I am having issue with.

@isTest
public class RegistrationControllerTest {


    static testMethod void testgetSelectedCourses(){
        // test to make sure courses selected are processed in step 2 - next button on studentregistrationstep2
        Account a = new Account(Name='Test Account', ufid__c='12345678');
        insert(a);

        //need program enrollent for student - this will trigger "AddCourses" trigger which will populate rest of the fields needed
        //Program__c is MS Forensic Science and Semester_Start__c is Summer 2015 B
        Program_Enrollment__c pe = new Program_Enrollment__c(Program__c='a02G000000CSRi7', Semester_Start__c='a041600000wTWuR',Student__c=a.id);
        insert(pe);

        test.startTest();

        //This will run the constructor of the controller
        RegistrationController RegCon = new RegistrationController();

        //Now we can test our action function on the controller
        RegCon.searchstring = a.ufid__c;
        RegCon.search();
        RegCon.getEnrolled();

        //manitpulate checkedPE to select a program enrollment in the wrapper on pg.1 of wizard
        RegCon.peList[0].checkedPE=true;

        RegCon.step1();

        RegCon.getselectedPE();

        RegCon.getCourses();

        //manipulate checkedCourses to select a course in the wrapper on pg.2 of the wizard
        RegCon.courseList[0].checkedCourses=true;

        RegCon.step2();

        test.stopTest();

        // verify getEnrolled method is returning records of enrolled courses
        system.assertNotEquals(RegCon.selectedCourses, null);
    }


}

I don't think you need to reference the VF pages, if you do, let me know. Thank you again for taking the time to help me :) Nic.

1 Answer 1

2

The quick fix is to add the annotation @isTest(SeeAllData=true) to your class. This is because the default for test classes now is that they cannot see any of your org's data.

This is not recommended, however - Relying on preexisting data is fragile. You should really examine all the data you are dependent on and built it all up here.

For example, you'l need to build up all the related records that you reference by Id in your test code and insert them into the database (test data gets removed at the end of the test)

Specifically, I can't see any insert of any Course__c records - and since you aren't using the annotation, your query won't find any.

I use a test data generator class in most of my projects, so that I have all the dependencies built up when I retrieve a particular type of object. It makes things a lot easier.

Here is an example.

Another data generation example - this one handles all cascading dependencies automagically!

3
  • You my friend, are my hero! I do believe you are absolutely correct, I should be building my own data to test as well. However, I knew that this should work since the Program_Enrollment__c (pe) I was inserting already has it's courses attached. I will work on inserting all test data in there though, that absolutely makes sense. So thanks for the answer, and the advice! May 24, 2015 at 21:56
  • No worries bro. I've added another link that I just found that generates all your dependencies. It's awesome. I haven't added it as a package, just copied the classes (with the copywrite info intact). It's working great! May 24, 2015 at 22:14
  • Oh wow, that is great. I appreciate your time in passing that along as well, thank you again! May 24, 2015 at 22:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .