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
Steve CairneySteve Cairney 

List out of bounds

Hi, I'm trying to load test data into a @isTest but I need to account for Lists and I can't find the right solution, the error is always that the list is out of bounds. I need to load test data for deployment into my org (in the sandbox I was using seeAllData)

The webservice class looks like this (jsut the GET section here)
 
webservice static String GetBookingDetails(ID id) {
    JSONGenerator jsonGenerator = JSON.createGenerator(true);
          
      ItsApproved_Booking__c booking = [SELECT Id, Name, Booking_Title__c, Customer_Reference__c, Incharge_Date__c FROM ItsApproved_Booking__c WHERE Id = :id];

      jsonGenerator.writeStartObject(); // Booking      
      //jsonGenerator.writeStringField('CompanyId', '798365d8-4278-4b16-a330-c4a3a9e1f91f'); // Staging Company Id
      //jsonGenerator.writeNumberField('UserId', 84); // Staging Company Id
      jsonGenerator.writeStringField('CompanyId', '042D7C6D-00E4-4C81-901A-BC8F8B545441'); // Live Company Id
      jsonGenerator.writeNumberField('UserId', 96); // Live User Id
      jsonGenerator.writeStringField('BookingTitle', booking.Booking_Title__c);
      jsonGenerator.writeStringField('CustomerReference', booking.Customer_Reference__c);
      jsonGenerator.writeStringField('CustomerBookingId', booking.Name);
      jsonGenerator.writeDateTimeField('InchargeDate', booking.Incharge_Date__c);

      List<ItsApproved_Product__c> products = [SELECT Id, IAProduct__c, Booking_Reference__c FROM ItsApproved_Product__c WHERE Booking_Reference__c = :Id];

      jsonGenerator.writeFieldName('Products');
      jsonGenerator.writeStartArray(); // Products
      for(ItsApproved_Product__c p: products)
      {
        List<IA_Product__c> IAProducts = [SELECT Id, Code__c FROM IA_Product__c WHERE Id = :p.IAProduct__c];

        jsonGenerator.writeStartObject(); // Products
        jsonGenerator.writeStringField('ProductionCode', IAProducts[0].Code__c);           
        jsonGenerator.writeStringField('CustomerProductReference', IAProducts[0].Code__c);           

        List<ItsApproved_Design__c> designs = [SELECT Id, Artwork_Title__c FROM ItsApproved_Design__c WHERE Product_Reference__c = :p.Id];

        jsonGenerator.writeFieldName('Designs');
        jsonGenerator.writeStartArray(); // Designs
        for(ItsApproved_Design__c d: designs)
        {
          jsonGenerator.writeStartObject();
          jsonGenerator.writeStringField('CustomerDesignId', d.Id);           
          jsonGenerator.writeStringField('DesignName', d.Artwork_Title__c);           

          List<ItsApproved_Delivery__c> deliveries = [SELECT Id, IADepot__c, Quantity__c FROM ItsApproved_Delivery__c WHERE ItsApproved_Design__c = :d.Id];

          jsonGenerator.writeFieldName('Deliveries');
          jsonGenerator.writeStartArray(); // Deliveries
          for(ItsApproved_Delivery__c del: deliveries)
          {
            List<IADepot__c> IADepots = [SELECT Id, Depot_Code__c FROM IADepot__c WHERE Id = :del.IADepot__c];

            jsonGenerator.writeStartObject(); // Deliveries
            jsonGenerator.writeStringField('DeliveryId', del.Id);           
            jsonGenerator.writeStringField('DepotCode', IADepots[0].Depot_Code__c);
            jsonGenerator.writeNumberField('Quantity', del.Quantity__c);
            jsonGenerator.writeEndObject(); // Deliveries
          }
          jsonGenerator.writeEndArray();  // Deliveries

          jsonGenerator.writeEndObject(); // Designs
        }
        jsonGenerator.writeEndArray(); // Designs

        jsonGenerator.writeEndObject(); // Products
      }
      jsonGenerator.writeEndArray(); // Products

      jsonGenerator.writeEndObject(); // Booking
        
      return jsonGenerator.getAsString();        
    }

And here's my test class, as you can see I've not faciliated any List data yet as I can't work out the best approach. If we use the first List as an example
 
List<ItsApproved_Product__c> products = [SELECT Id, IAProduct__c, Booking_Reference__c FROM ItsApproved_Product__c WHERE Booking_Reference__c = :Id];

How do I load test data with at least 1 record in the list?

@isTest here
 
@isTest
public class Testing_ItsApprovedWebServices {

	@isTest public static  void ItsApprovedWebServicesTest(){
        ItsApproved_Booking__c bookingdetails = new ItsApproved_Booking__c(Booking_Title__c = 'Test', Customer_Reference__c = 'Test',Incharge_Date__c = System.today() );
    	insert bookingdetails;
        
        ItsApproved_Product__c productdetails = new ItsApproved_Product__c(Booking_Reference__c = bookingdetails.Id);
        insert productdetails;

        IA_Product__c iaproduct = new IA_Product__c(Code__c = '606');
        insert iaproduct;

        ItsApproved_Design__c designdetails = new ItsApproved_Design__c(Product_Reference__c = productdetails.Id);
        insert designdetails;
        
        ItsApproved_Delivery__c deliverydetails = new ItsApproved_Delivery__c(Product__c = productdetails.Id, ItsApproved_Design__c = designdetails.Id);
        insert deliverydetails;
        
        Test.startTest();
        Test.setMock(HttpCalloutMock.class, new MockHttpResponseGenerator()); 

        String username = ItsApprovedWebServices.Login('test');
        String details = ItsApprovedWebservices.GetBookingDetails(bookingdetails.Id);
		
        Test.setMock(HttpCalloutMock.class, new MockHttpResponseGenerator2()); 
        String postbooking = ItsApprovedWebServices.PostBooking('{"test" : "test"}','authorization_id');
		
        Test.stopTest();
    }		
}



 
Best Answer chosen by Steve Cairney
Steve CairneySteve Cairney
Hi Chris, just to let you know that I managed to sort this. here's the code, all that was missing was referencing the created test data in the loop
 
//this is where your class begins
@isTest
public class Testing_ItsApprovedWebServices {

	//this is a general method to setup test data
	private static ID SetUpTestData(){

        List<IA_Product__c> IAProducts = new List<IA_Product__c>();
        IAProducts.add(new IA_Product__c(Code__c = '606'));
        insert IAProducts;

        List<IADepot__c> IADepots = new List<IADepot__c>();
        IADepots.add(new IADepot__c(Depot_Code__c = 'Test Depot'));
        insert IADepots;

        List<IA_Product__c> products = [SELECT Id FROM IA_Product__c WHERE Code__c = '606'];
        List<IADepot__c> depots = [SELECT Id FROM IADepot__c WHERE Depot_Code__c = 'Test Depot'];
        
        ItsApproved_Booking__c bookingdetails = new ItsApproved_Booking__c(Booking_Title__c = 'Test', Customer_Reference__c = 'Test',Incharge_Date__c = System.today() );
    	insert bookingdetails;
        
        for(IA_Product__c p: products)
        {
    	    ItsApproved_Product__c productdetails = new ItsApproved_Product__c(Booking_Reference__c = bookingdetails.Id, IAProduct__c = p.Id);
	        insert productdetails;
            
            ItsApproved_Design__c designdetails = new ItsApproved_Design__c(Product_Reference__c = productdetails.Id, Artwork_Title__c = 'Test Artwork');
            insert designdetails;
            
            for(IADepot__c d: depots)
            {
                ItsApproved_Delivery__c deliverydetails = new ItsApproved_Delivery__c(Product__c = productdetails.Id, ItsApproved_Design__c = designdetails.Id, IADepot__c = d.Id, Quantity__c = 10);
                insert deliverydetails;
            }
        }
        return bookingdetails.Id;
	}

	//this is your actual test method
	@isTest public static  void ItsApprovedWebServicesTest(){
        
       	ID bookingid = SetupTestData(); //this will create your test data
        
        Test.startTest();
        Test.setMock(HttpCalloutMock.class, new MockHttpResponseGenerator()); 

        String username = ItsApprovedWebServices.Login('test');
        String details = ItsApprovedWebservices.GetBookingDetails(bookingid);
		
        Test.setMock(HttpCalloutMock.class, new MockHttpResponseGenerator2()); 
        String postbooking = ItsApprovedWebServices.PostBooking('{"test" : "test"}','authorization_id');
		
        Test.stopTest();
    }		
}

 

All Answers

Chris Gary CloudPerformerChris Gary CloudPerformer
Put your insert statements in between your Test.startTest() and Test.stopTest() methods.  See if that works for you.  I hope this helps.
Steve CairneySteve Cairney
Hi Chris, I've tried that previously but there can't be a DML and CallOut at the same time so it fails
Chris Gary CloudPerformerChris Gary CloudPerformer
Just a thought - a few weeks ago , I had an issue accidentally using reserved names as variable names - I noticed in your code, you are naming your vairable 'Id' - but Id is also a Variable type.  Can you try replacing where you use 'Id' as a variable name with something else, like 'idIn'?
Steve CairneySteve Cairney
I don't think that's the problem Chris, this was working in the sandbox with (seeAllData=true) but becuase I'd harcoded the record in. I can't do that for production.

I'm been spitballing and I'm wondering if this might be on the right track?
 
@isTest
public class Testing_ItsApprovedWebServices {

	@isTest public static  void ItsApprovedWebServicesTest() {
   		public void createTestRecords(Integer numProducts){
        ItsApproved_Booking__c bookingdetails = new ItsApproved_Booking__c(Booking_Title__c = 'Test', Customer_Reference__c = 'Test',Incharge_Date__c = System.today() );
    	insert bookingdetails;
        
            List<ItsApproved_Product__c> products = new List<ItsApproved_Product__c>();
            
            for(Integer i=0;i<numProducts;i++){
                ItsApproved_Product__c p = new ItsApproved_Product__c(Booking_Reference__c = bookingdetails.Id + i);
                products.add(p);
            }
            insert products;
        }
        
        @isTest
		private class MyTestClass {
    	static testmethod void test1() {
        Testing_ItsApprovedWebServices.createTestRecords(1);
        // not sure what to put here
   		}
		}

Weird thing is it's telling me there's a syntax error on line 5  around here: @isTest public static  void ItsApprovedWebServicesTest() {
           public void createTestRecords(Integer numProducts){

expecting a semi-colon, found '('

So I can't save it...
Chris Gary CloudPerformerChris Gary CloudPerformer
Its because on line 5, you are attempting to declare a function within a function - not allowed on salesforce.  Remove the 'public void' - you are already in the 'ItsApprovedWebServicesTest' method.
Steve CairneySteve Cairney
Never tried this before, I'm trying to follow this, doesn't seem vastly different to what I'm trying to do?

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_testing_utility_classes.htm
Chris Gary CloudPerformerChris Gary CloudPerformer
No, in pricinple its not different from what you are trying to do - you just have a small syntax error on line 5.  Remove 'public void' - that is the beginning of a Method declaration.  You can't declare a new method when you are inside an existing one.

I understand you can't hardcode the Id in because it does not exist in production - you are on the right track with creating the data and then passing the Id of the newly created record to your object and method.  The problem is the parameters are getting confused as 'Types', and are therefore returning null, so when your query executes, it returns nothing because there are no records where Id='null'.  Remember Apex is case insensitive, so there is no difference between Id ID and id.  I hope this clarifies it.
Steve CairneySteve Cairney
Hi Gary, I've changed the variable in the webservice to differentiate it from ID, Id or id (I used your example of idIn)
 
webservice static String GetBookingDetails(Id idIn) {
    JSONGenerator jsonGenerator = JSON.createGenerator(true);
          
      ItsApproved_Booking__c booking = [SELECT Id, Name, Booking_Title__c, Customer_Reference__c, Incharge_Date__c FROM ItsApproved_Booking__c WHERE Id = :idIn];

      jsonGenerator.writeStartObject(); // Booking      
      //jsonGenerator.writeStringField('CompanyId', '798365d8-4278-4b16-a330-c4a3a9e1f91f'); // Staging Company Id
      //jsonGenerator.writeNumberField('UserId', 84); // Staging Company Id
      jsonGenerator.writeStringField('CompanyId', '042D7C6D-00E4-4C81-901A-BC8F8B545441'); // Live Company Id
      jsonGenerator.writeNumberField('UserId', 96); // Live User Id
      jsonGenerator.writeStringField('BookingTitle', booking.Booking_Title__c);
      jsonGenerator.writeStringField('CustomerReference', booking.Customer_Reference__c);
      jsonGenerator.writeStringField('CustomerBookingId', booking.Name);
      jsonGenerator.writeDateTimeField('InchargeDate', booking.Incharge_Date__c);

      List<ItsApproved_Product__c> products = [SELECT Id, IAProduct__c, Booking_Reference__c FROM ItsApproved_Product__c WHERE Booking_Reference__c = :idIn];

Now, when I try to remove the public void from the test class like you suggest, a new syntax error appears. Am I missing something here?
 
@isTest public static  void ItsApprovedWebServicesTest() {
   		createTestRecords(Integer numProducts){ //error expecting right parentheses, found 'numProducts'

 
Chris Gary CloudPerformerChris Gary CloudPerformer
Here is the test class to help you out. Let me know if you have any questions.  I commented it for you.
//this is where your class begins
@isTest
public class Testing_ItsApprovedWebServices {

	//this is a general method to setup test data
	private static void SetUpTestData(){
		ItsApproved_Booking__c bookingdetails = new ItsApproved_Booking__c(Booking_Title__c = 'Test', Customer_Reference__c = 'Test',Incharge_Date__c = System.today() );
    	insert bookingdetails;
        
        ItsApproved_Product__c productdetails = new ItsApproved_Product__c(Booking_Reference__c = bookingdetails.Id);
        insert productdetails;

        IA_Product__c iaproduct = new IA_Product__c(Code__c = '606');
        insert iaproduct;

        ItsApproved_Design__c designdetails = new ItsApproved_Design__c(Product_Reference__c = productdetails.Id);
        insert designdetails;
        
        ItsApproved_Delivery__c deliverydetails = new ItsApproved_Delivery__c(Product__c = productdetails.Id, ItsApproved_Design__c = designdetails.Id);
        insert deliverydetails;
	}

	//this is your actual test method
	@isTest public static  void ItsApprovedWebServicesTest(){
        
        SetupTestData(); //this will create your test data
        
        Test.startTest();
        Test.setMock(HttpCalloutMock.class, new MockHttpResponseGenerator()); 

        String username = ItsApprovedWebServices.Login('test');
        String details = ItsApprovedWebservices.GetBookingDetails(bookingdetails.Id);
		
        Test.setMock(HttpCalloutMock.class, new MockHttpResponseGenerator2()); 
        String postbooking = ItsApprovedWebServices.PostBooking('{"test" : "test"}','authorization_id');
		
        Test.stopTest();
    }		
}

 
Steve CairneySteve Cairney
Hi Chris, just to let you know that I managed to sort this. here's the code, all that was missing was referencing the created test data in the loop
 
//this is where your class begins
@isTest
public class Testing_ItsApprovedWebServices {

	//this is a general method to setup test data
	private static ID SetUpTestData(){

        List<IA_Product__c> IAProducts = new List<IA_Product__c>();
        IAProducts.add(new IA_Product__c(Code__c = '606'));
        insert IAProducts;

        List<IADepot__c> IADepots = new List<IADepot__c>();
        IADepots.add(new IADepot__c(Depot_Code__c = 'Test Depot'));
        insert IADepots;

        List<IA_Product__c> products = [SELECT Id FROM IA_Product__c WHERE Code__c = '606'];
        List<IADepot__c> depots = [SELECT Id FROM IADepot__c WHERE Depot_Code__c = 'Test Depot'];
        
        ItsApproved_Booking__c bookingdetails = new ItsApproved_Booking__c(Booking_Title__c = 'Test', Customer_Reference__c = 'Test',Incharge_Date__c = System.today() );
    	insert bookingdetails;
        
        for(IA_Product__c p: products)
        {
    	    ItsApproved_Product__c productdetails = new ItsApproved_Product__c(Booking_Reference__c = bookingdetails.Id, IAProduct__c = p.Id);
	        insert productdetails;
            
            ItsApproved_Design__c designdetails = new ItsApproved_Design__c(Product_Reference__c = productdetails.Id, Artwork_Title__c = 'Test Artwork');
            insert designdetails;
            
            for(IADepot__c d: depots)
            {
                ItsApproved_Delivery__c deliverydetails = new ItsApproved_Delivery__c(Product__c = productdetails.Id, ItsApproved_Design__c = designdetails.Id, IADepot__c = d.Id, Quantity__c = 10);
                insert deliverydetails;
            }
        }
        return bookingdetails.Id;
	}

	//this is your actual test method
	@isTest public static  void ItsApprovedWebServicesTest(){
        
       	ID bookingid = SetupTestData(); //this will create your test data
        
        Test.startTest();
        Test.setMock(HttpCalloutMock.class, new MockHttpResponseGenerator()); 

        String username = ItsApprovedWebServices.Login('test');
        String details = ItsApprovedWebservices.GetBookingDetails(bookingid);
		
        Test.setMock(HttpCalloutMock.class, new MockHttpResponseGenerator2()); 
        String postbooking = ItsApprovedWebServices.PostBooking('{"test" : "test"}','authorization_id');
		
        Test.stopTest();
    }		
}

 
This was selected as the best answer
Chris Gary CloudPerformerChris Gary CloudPerformer
Cool! Glad you were able to figure it out!