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
LooseLipsLooseLips 

Testing an Apex Class with @Future - Help Needed

Ok gentlemen - I need some assistance.

 

I'm a relative newbie to this although I making decent progress punctuated with a a few hours here of despair.

 

I currently have a custom object being part populated through the API - I then have written the following class which goes away to an external API and pulls back some more fields completed the data - and it works well. But at when I went live with this I wasn't too up on test methods. As such, the class has not got any and thankfully due to the pre-installed packages from Salesforce I am just hovering above 75% through pure luck.

 

As such, I have this in production and luckily working with triggers but I now need to update the test method or I can't deploy some updated functionality - if anyone have used the deployment functionality you will know what I mean.

 

Here's the class ignore the test at the bottom - that was purely to get trigger above 0%. My code coverage on the class for this is 0%.

 

Can you give me some pointers on the following code? Now I've seen the apex instructions on breaking your callouts in 3 sections but I can't seem to make that fit.

 

Any thoughts - any suggestions welcome... like I said currently at 0%....

 

 

public class IncidentCouncilUpdater {

  //Future annotation to mark the method as async.
  @Future(callout=true)
  public static void updateIncident(ID IncidentID) {
  
  Incident__c myCoordinates = [SELECT latitude__c, longitude__c
                             FROM Incident__c
                             WHERE Id = :IncidentID];  
  System.debug('myCoordinates: ' + myCoordinates);  
  
  String myLat = myCoordinates.latitude__c;
  String myLong = myCoordinates.longitude__c;          
  System.debug('myLat: ' + myLat);
  System.debug('myLong: ' + myLong);     
  
  //Create end point from fields in the database
  String StrEndPoint = 
  'http://www.uk-postcodes.com/latlng/'+myLat+','+myLong+'.xml';
  
  System.debug('StrEndPoint: ' + StrEndPoint);
  
    //construct an HTTP request
    HttpRequest req = new HttpRequest();
    req.setHeader('Content-Type', 'text/xml');
    //req.setEndpoint('http://www.uk-postcodes.com/latlng/53.24354,-2.34567.xml');
    req.setEndpoint(strEndPoint);
    req.setMethod('GET');
    req.setTimeout(60000);
    
    //send the request
    Http http = new Http();
    HttpResponse res = http.send(req);
    
    // Log the XML content  
    Dom.Document doc = res.getBodyDocument(); 
    
    // print out specific elements by finding the node address 
    dom.XmlNode location = doc.getRootElement()
    .getChildElement('administrative',null)
    .getChildElement('district',null);  
    
    System.debug('location: ' + location);   
    
    // print out specific elements by finding the node address 
    dom.XmlNode location2 = doc.getRootElement();
      System.debug('location2: ' + location2); 
      
    // gets the content from the XML
    String district_title;
    String postcode;
    district_title = location.getChildElement('title', null).getText();
    postcode = location2.getChildElement('postcode', null).getText();
    System.debug('district_title: ' + district_title);  
    System.debug('postcode: ' + postcode);
    
    //update Incident
    Incident__c Inc = new Incident__c(Id=IncidentID);
    Inc.Council_Name_Text__c = district_title;
    Inc.Incident_Postcode__c = postcode;
    update Inc; 
     
}

    static testMethod void testIncidentCouncilUpdater(){
   
    Incident__c Inc1 = new Incident__c(name='Other', latitude__c='53.54489', longitude__c='-2.44467');
    return inc1.id;
    String StrEndPoint = 'http://www.uk-postcodes.com/latlng/53.54489,-2.44467.xml';
    
    HttpRequest req = new HttpRequest();
    req.setEndpoint(strEndPoint);
    req.setMethod('GET');
    req.setTimeout(60000);
    
    
    Inc1.Council_Name_Text__c = 'Salford City Council';
    Inc1.Incident_Postcode__c = 'M30 9QU';
    update Inc1;
}

}

 

 

Here's the trigger...

 

 

trigger XMLUpdater on Incident__c (after insert) {

  System.debug('Making future call to update account');
  for (Incident__c Inc : Trigger.New) {
    //Call future method to update account
    //with data from external server.
    //This is a async calls, it returns right away, after
    //enqueuing the request.

    IncidentCouncilUpdater.updateIncident(Inc.Id);
  }

}

 

 

 

 

 

Best Answer chosen by Admin (Salesforce Developers) 
smillssmills

I rewrote your class to allow you to get a better test code coverage.  I tested in my Developer Edition and got 94% test code coverage.  I couldn't test 4 lines and that is due to the fact that you cannot call a webservice in test methods, so as the links state you have to simulate it.

 

Some classes are defined with the virtual keyword because I usually overwrite them in the test code coverage, but your code didn't need it, but maybe will in the future.

 

 

public virtual class IncidentCouncilUpdater {

   public static boolean isApexTest = false;
   private static HttpRequest req = new HttpRequest();
   private static HttpResponse res = new HttpResponse();
   private static Http http = new Http();
   private static String resBody= '';
   private static String URLprefix;
   private static String path;
   private static Integer StatusCode;

   public IncidentCouncilUpdater() {}
  	
   public virtual HttpRequest createRequest(String imethod, String ipath) {
        system.debug('Inside createRequest, method= ' + imethod + ', path=' + ipath);
        req = new HttpRequest();
        URLprefix = 'http://www.uk-postcodes.com/latlng/';
        
        req.setEndpoint(URLprefix + ipath + '.xml');
        req.setMethod('GET');
        req.setCompressed(true); // otherwise we hit a limit of 32000
        req.setTimeout(60000); // timeout in milliseconds
        return req;
    }

    protected virtual HttpResponse execute(HttpRequest ireq) {
        System.debug(LoggingLevel.FINE, '\n\nReq: \n' + ireq + '\n\n');
        HttpResponse ires = http.send(ireq);
        String iresBody = getResponseBody(ires, ireq);
        System.debug(LoggingLevel.FINE, '\n\nResp: \n' + iresBody);
        return ires;
    }
    
    protected virtual HttpResponse executeAsync(HttpRequest ireq) {
		HttpResponse r = new HttpResponse();
		return r;
	}	

    public virtual String getResponseBody(HttpResponse r, HttpRequest ireq) {
        return r.getBody(); 
    }
  
  	protected virtual String getResponseBodyAsync(HttpResponse r, HttpRequest ireq) {
		String ep = ireq.getEndpoint();
   		URLprefix = 'http://www.uk-postcodes.com/latlng/';

    	System.debug('Inside getResponseBodyAsync, URLPrefix=' + URLPrefix);
		System.debug('GET RESPONSE FOR * ' + ep + ' *\n\n');
		String body = '';

		if((ep.equals(URLprefix + '53.54489,-2.44467.xml')) )	 {
				//http://www.uk-postcodes.com/latlng/53.54489,-2.44467.xml
			body = checkIncidentQuery();
		}
			
		System.debug(LoggingLevel.INFO, '\n\nReturning body: \n' + body + '\n\n');
			return body;
	}

  //Future annotation to mark the method as async.
  @Future(callout=true)
  public static void updateIncident(ID IncidentID) {
	  Incident__c myCoordinates = [SELECT latitude__c, longitude__c
	                             FROM Incident__c
	                             WHERE Id = :IncidentID];  
	  System.debug('myCoordinates: ' + myCoordinates);  
	  
	  String myLat = myCoordinates.latitude__c;
	  String myLong = myCoordinates.longitude__c;          
	  System.debug('myLat: ' + myLat);
	  System.debug('myLong: ' + myLong);     
	  
	  IncidentCouncilUpdater i = new IncidentCouncilUpdater();
	  IncidentCouncilUpdater.path = myCoordinates.latitude__c + ',' + myCoordinates.longitude__c;
	  IncidentCouncilUpdater.req = i.createRequest('GET', '' + path);
	  system.debug('isApexTest=' + IncidentCouncilUpdater.isApexTest + ', req=' + req.toString());
	  if (!IncidentCouncilUpdater.isApexTest) {
	  	IncidentCouncilUpdater.res = i.execute(req); 
	  } else {
	  	IncidentCouncilUpdater.res = i.executeAsync(req);
	  }
	  system.debug('res=' + IncidentCouncilUpdater.res.toString());
	  IncidentCouncilUpdater.StatusCode = IncidentCouncilUpdater.res.getStatusCode();
	  system.debug('StatusCode=' + IncidentCouncilUpdater.StatusCode + ', isApexTest=' + IncidentCouncilUpdater.isApexTest);
	  if (IncidentCouncilUpdater.isApexTest) {
		IncidentCouncilUpdater.resBody = i.getResponseBodyAsync(res, req);
	  } else {
		if (StatusCode == 200)
			IncidentCouncilUpdater.resBody = i.getResponseBody(res, req);
	  }
	  Dom.Document domDoc = new Dom.Document();
        domDoc.load(IncidentCouncilUpdater.resBody);
        // print out specific elements by finding the node address 
	     dom.XmlNode location = domDoc.getRootElement()
	      .getChildElement('administrative',null)
	      .getChildElement('district',null);  
	      System.debug('location: ' + location);   
	
	      // print out specific elements by finding the node address 
	      dom.XmlNode location2 = domDoc.getRootElement();
	      System.debug('location2: ' + location2); 
	   
	      // gets the content from the XML
	      String district_title;
	      String postcode;
	      district_title = location.getChildElement('title', null).getText();
	      postcode = location2.getChildElement('postcode', null).getText();
	      System.debug('district_title: ' + district_title);  
	      System.debug('postcode: ' + postcode);
	
	      //update Incident
	      Incident__c Inc = new Incident__c(Id=IncidentID);
	      Inc.Council_Name_Text__c = district_title;
	      Inc.Incident_Postcode__c = postcode;
	      update Inc;  
          system.debug('********************Inc1 after (Callout & Update)=' + Inc);
	   }			
   
	  static String checkIncidentQuery() {
	    return '<result>' +
					'<postcode>BL5  1AL</postcode>' +
					'<geo>' +
						'<lat>53.545105</lat>' +
						'<lng>-2.44607</lng>' +
						'<easting>370538</easting>' +
						'<northing>405477</northing>' +
						'<geohash>http://geohash.org/gcw287dff7n0</geohash>' +
					'</geo>' +
					'<administrative>' +
						'<constituency>' +
							'<title>Bolton West</title>' +
							'<uri>http://statistics.data.gov.uk/id/parliamentary-constituency/053</uri>' +
							'<code>053</code>' +
						'</constituency>' +
						'<district>' +
							'<title>Bolton Borough Council</title>' +
							'<uri>http://statistics.data.gov.uk/id/local-authority/00BL</uri>' +
							'<snac>00BL</snac>' +
						'</district>' +
						'<ward>' +
							'<title>Hulton</title>' +
							'<uri>http://statistics.data.gov.uk/id/electoral-ward/00BLGK</uri>' +
							'<snac>00BLGK</snac>' +
						'</ward>' +
					'</administrative>' +
				'</result>';
	  } 
  
}

 

 

The test code for the above is below.  I wrote three test methods because I like to breakup some of the testing so I can see what is happening in the debug logs better.  The last two are basically going to fail because you cannot call webservices in test methods, but I use them to test the lines in the future call where the isApexTest logic is used.

 

 

@isTest
private class IncidentCouncilUpdaterTest {

	static testMethod void testFutureCallSuccess(){
	    Incident__c Inc1 = new Incident__c(name='Other', latitude__c='53.54489', longitude__c='-2.44467');
	    insert Inc1;
	    String StrEndPoint = 'http://www.uk-postcodes.com/latlng/' + Inc1.latitude__c + ',' + Inc1.longitude__c + '.xml';
	    IncidentCouncilUpdater.isApexTest = true;
	    Test.startTest();
	    	IncidentCouncilUpdater.updateIncident(Inc1.ID);
	    Test.stopTest();
	}
	static testMethod void testFutureCallFail(){
	    Incident__c Inc1 = new Incident__c(name='Other', latitude__c='53.54489', longitude__c='-2.44467');
	    insert Inc1;
	    String StrEndPoint = 'http://www.uk-postcodes.com/latlng/' + Inc1.latitude__c + ',' + Inc1.longitude__c + '.xml';
	    IncidentCouncilUpdater.isApexTest = false;
	    Test.startTest();
	    	IncidentCouncilUpdater.updateIncident(Inc1.ID);
	    Test.stopTest();
	}
	
	static testMethod void testgetResponseBody() {
	    Incident__c Inc1 = new Incident__c(name='Other', latitude__c='53.54489', longitude__c='-2.44467');
	    insert Inc1;
	    IncidentCouncilUpdater i= new IncidentCouncilUpdater();
	    String StrEndPoint = 'http://www.uk-postcodes.com/latlng/' + Inc1.latitude__c + ',' + Inc1.longitude__c + '.xml';
	    IncidentCouncilUpdater.isApexTest = false;
	    String path = Inc1.latitude__c + ',' + Inc1.longitude__c;
	    
	    Test.startTest();
	    	HttpResponse r = new HttpResponse();
		    HttpRequest ireq = i.createRequest('GET', '' + path);
	    	i.getResponseBody(r, ireq);
	    Test.stopTest();
	}

}

 

 

As stated above, I tested this in my Developers account and it works fine. I actually copied your trigger and created your Incident object to test.  When I created a new incident record, the trigger calls the future call which retrieves the data from the webservice and then updates the newly created Incident record.

 

Hope this helps!

All Answers

smillssmills

The first issue is that you cannot execute a 3rd party callout inside test code, but if you break the code into the three parts like you stated then you will be able to get over 75% coverage.  I actually broke my code into more than 4 parts because I am doing a lot of parsing and other things.  

 

I gained most of my knowledge to get my Apex code to pass test code coverage by using thethree articles below.  I am currently at 96% code coverage for my callout.

 

Apex Web Services and Callouts

Virtual Callout Testing

Testing HTTP Callouts

 

I ended up using the logic in 'Virtual Callout Testing' and it works great.  Once you understand the above, you should be able to write the test code without a problem.  Plus, you will learn a lot about HTTP Callouts and how Apex handles them.

 

Hope this helps

LooseLipsLooseLips

Thanks Smills - appreciate the links.

 

I decided to rewrite the class using the boolean to state whether it's a test or not and I've just about managed that. It's still working anyway.

 

However, I've just read the comments on that blog post and because I am using the @future callout it appears that I cannot use this approach!!!

 

Has anyone got any other thoughts in relation to the @future part of the code?

smillssmills
I doubt you will be able to get 100% code coverage, but if you post your rewritten code, I will try to assit you with some test code. Currently I have received 97% code coverage using future calls, but some lines cannot be tested so I am content with 97%
LooseLipsLooseLips

That would be a big help smills.

 

As I said I have rewritten the class below to allow for the boolena test method as highllighted in those links you said.

 

I am assuming that I will need to use the 

 

Test.startTest();

@Future Callout

Test.stopTest();

 

At the beginning to allow for the testing of the callout. Here's the code as it stands....

 

 

public class IncidentCouncilUpdater {

  public static boolean isApexTest = false;

  //Future annotation to mark the method as async.
  @Future(callout=true)
  public static void updateIncident(ID IncidentID) {
  
  Incident__c myCoordinates = [SELECT latitude__c, longitude__c
                             FROM Incident__c
                             WHERE Id = :IncidentID];  
  System.debug('myCoordinates: ' + myCoordinates);  
  
  String myLat = myCoordinates.latitude__c;
  String myLong = myCoordinates.longitude__c;          
  System.debug('myLat: ' + myLat);
  System.debug('myLong: ' + myLong);     
  
  //Create end point from fields in the database
  String StrEndPoint = 
  'http://www.uk-postcodes.com/latlng/'+myLat+','+myLong+'.xml';
  System.debug('StrEndPoint: ' + StrEndPoint);
  
        //construct an HTTP request
        HttpRequest req = new HttpRequest();
        req.setHeader('Content-Type', 'text/xml'); 
        req.setEndpoint(strEndPoint);
        req.setMethod('GET');
        req.setTimeout(60000);
        
           String result = '';
           if (!isApexTest){
        
           //send the request 
           Http http = new Http();
           HttpResponse res = http.send(req);
           Dom.Document doc = res.getBodyDocument(); 
           
           // print out specific elements by finding the node address 
           dom.XmlNode location = doc.getRootElement()
          .getChildElement('administrative',null)
          .getChildElement('district',null);  
          System.debug('location: ' + location);   
    
          // print out specific elements by finding the node address 
          dom.XmlNode location2 = doc.getRootElement();
          System.debug('location2: ' + location2); 
       
          // gets the content from the XML
          String district_title;
          String postcode;
          district_title = location.getChildElement('title', null).getText();
          postcode = location2.getChildElement('postcode', null).getText();
          System.debug('district_title: ' + district_title);  
          System.debug('postcode: ' + postcode);
    
          //update Incident
          Incident__c Inc = new Incident__c(Id=IncidentID);
          Inc.Council_Name_Text__c = district_title;
          Inc.Incident_Postcode__c = postcode;
          update Inc;  
          } else {
          result = '<result><postcode>M30  9QU</postcode><geo><lat>53.488697</lat><lng>-2.34835</lng><easting>376983</easting><northing>399166</northing><geohash>http://geohash.org/gcw2693fprz6</geohash></geo><administrative><constituency><title>Eccles</title><uri>http://statistics.data.gov.uk/id/parliamentary-constituency/155</uri><code>155</code></constituency><district><title>Salford City Council</title><uri>http://statistics.data.gov.uk/id/local-authority/00BR</uri><snac>00BR</snac></district><ward><title>Eccles</title><uri>http://statistics.data.gov.uk/id/electoral-ward/00BRGC</uri><snac>00BRGC</snac></ward></administrative></result>';
          }     
    }        
}

 

 

smillssmills

I rewrote your class to allow you to get a better test code coverage.  I tested in my Developer Edition and got 94% test code coverage.  I couldn't test 4 lines and that is due to the fact that you cannot call a webservice in test methods, so as the links state you have to simulate it.

 

Some classes are defined with the virtual keyword because I usually overwrite them in the test code coverage, but your code didn't need it, but maybe will in the future.

 

 

public virtual class IncidentCouncilUpdater {

   public static boolean isApexTest = false;
   private static HttpRequest req = new HttpRequest();
   private static HttpResponse res = new HttpResponse();
   private static Http http = new Http();
   private static String resBody= '';
   private static String URLprefix;
   private static String path;
   private static Integer StatusCode;

   public IncidentCouncilUpdater() {}
  	
   public virtual HttpRequest createRequest(String imethod, String ipath) {
        system.debug('Inside createRequest, method= ' + imethod + ', path=' + ipath);
        req = new HttpRequest();
        URLprefix = 'http://www.uk-postcodes.com/latlng/';
        
        req.setEndpoint(URLprefix + ipath + '.xml');
        req.setMethod('GET');
        req.setCompressed(true); // otherwise we hit a limit of 32000
        req.setTimeout(60000); // timeout in milliseconds
        return req;
    }

    protected virtual HttpResponse execute(HttpRequest ireq) {
        System.debug(LoggingLevel.FINE, '\n\nReq: \n' + ireq + '\n\n');
        HttpResponse ires = http.send(ireq);
        String iresBody = getResponseBody(ires, ireq);
        System.debug(LoggingLevel.FINE, '\n\nResp: \n' + iresBody);
        return ires;
    }
    
    protected virtual HttpResponse executeAsync(HttpRequest ireq) {
		HttpResponse r = new HttpResponse();
		return r;
	}	

    public virtual String getResponseBody(HttpResponse r, HttpRequest ireq) {
        return r.getBody(); 
    }
  
  	protected virtual String getResponseBodyAsync(HttpResponse r, HttpRequest ireq) {
		String ep = ireq.getEndpoint();
   		URLprefix = 'http://www.uk-postcodes.com/latlng/';

    	System.debug('Inside getResponseBodyAsync, URLPrefix=' + URLPrefix);
		System.debug('GET RESPONSE FOR * ' + ep + ' *\n\n');
		String body = '';

		if((ep.equals(URLprefix + '53.54489,-2.44467.xml')) )	 {
				//http://www.uk-postcodes.com/latlng/53.54489,-2.44467.xml
			body = checkIncidentQuery();
		}
			
		System.debug(LoggingLevel.INFO, '\n\nReturning body: \n' + body + '\n\n');
			return body;
	}

  //Future annotation to mark the method as async.
  @Future(callout=true)
  public static void updateIncident(ID IncidentID) {
	  Incident__c myCoordinates = [SELECT latitude__c, longitude__c
	                             FROM Incident__c
	                             WHERE Id = :IncidentID];  
	  System.debug('myCoordinates: ' + myCoordinates);  
	  
	  String myLat = myCoordinates.latitude__c;
	  String myLong = myCoordinates.longitude__c;          
	  System.debug('myLat: ' + myLat);
	  System.debug('myLong: ' + myLong);     
	  
	  IncidentCouncilUpdater i = new IncidentCouncilUpdater();
	  IncidentCouncilUpdater.path = myCoordinates.latitude__c + ',' + myCoordinates.longitude__c;
	  IncidentCouncilUpdater.req = i.createRequest('GET', '' + path);
	  system.debug('isApexTest=' + IncidentCouncilUpdater.isApexTest + ', req=' + req.toString());
	  if (!IncidentCouncilUpdater.isApexTest) {
	  	IncidentCouncilUpdater.res = i.execute(req); 
	  } else {
	  	IncidentCouncilUpdater.res = i.executeAsync(req);
	  }
	  system.debug('res=' + IncidentCouncilUpdater.res.toString());
	  IncidentCouncilUpdater.StatusCode = IncidentCouncilUpdater.res.getStatusCode();
	  system.debug('StatusCode=' + IncidentCouncilUpdater.StatusCode + ', isApexTest=' + IncidentCouncilUpdater.isApexTest);
	  if (IncidentCouncilUpdater.isApexTest) {
		IncidentCouncilUpdater.resBody = i.getResponseBodyAsync(res, req);
	  } else {
		if (StatusCode == 200)
			IncidentCouncilUpdater.resBody = i.getResponseBody(res, req);
	  }
	  Dom.Document domDoc = new Dom.Document();
        domDoc.load(IncidentCouncilUpdater.resBody);
        // print out specific elements by finding the node address 
	     dom.XmlNode location = domDoc.getRootElement()
	      .getChildElement('administrative',null)
	      .getChildElement('district',null);  
	      System.debug('location: ' + location);   
	
	      // print out specific elements by finding the node address 
	      dom.XmlNode location2 = domDoc.getRootElement();
	      System.debug('location2: ' + location2); 
	   
	      // gets the content from the XML
	      String district_title;
	      String postcode;
	      district_title = location.getChildElement('title', null).getText();
	      postcode = location2.getChildElement('postcode', null).getText();
	      System.debug('district_title: ' + district_title);  
	      System.debug('postcode: ' + postcode);
	
	      //update Incident
	      Incident__c Inc = new Incident__c(Id=IncidentID);
	      Inc.Council_Name_Text__c = district_title;
	      Inc.Incident_Postcode__c = postcode;
	      update Inc;  
          system.debug('********************Inc1 after (Callout & Update)=' + Inc);
	   }			
   
	  static String checkIncidentQuery() {
	    return '<result>' +
					'<postcode>BL5  1AL</postcode>' +
					'<geo>' +
						'<lat>53.545105</lat>' +
						'<lng>-2.44607</lng>' +
						'<easting>370538</easting>' +
						'<northing>405477</northing>' +
						'<geohash>http://geohash.org/gcw287dff7n0</geohash>' +
					'</geo>' +
					'<administrative>' +
						'<constituency>' +
							'<title>Bolton West</title>' +
							'<uri>http://statistics.data.gov.uk/id/parliamentary-constituency/053</uri>' +
							'<code>053</code>' +
						'</constituency>' +
						'<district>' +
							'<title>Bolton Borough Council</title>' +
							'<uri>http://statistics.data.gov.uk/id/local-authority/00BL</uri>' +
							'<snac>00BL</snac>' +
						'</district>' +
						'<ward>' +
							'<title>Hulton</title>' +
							'<uri>http://statistics.data.gov.uk/id/electoral-ward/00BLGK</uri>' +
							'<snac>00BLGK</snac>' +
						'</ward>' +
					'</administrative>' +
				'</result>';
	  } 
  
}

 

 

The test code for the above is below.  I wrote three test methods because I like to breakup some of the testing so I can see what is happening in the debug logs better.  The last two are basically going to fail because you cannot call webservices in test methods, but I use them to test the lines in the future call where the isApexTest logic is used.

 

 

@isTest
private class IncidentCouncilUpdaterTest {

	static testMethod void testFutureCallSuccess(){
	    Incident__c Inc1 = new Incident__c(name='Other', latitude__c='53.54489', longitude__c='-2.44467');
	    insert Inc1;
	    String StrEndPoint = 'http://www.uk-postcodes.com/latlng/' + Inc1.latitude__c + ',' + Inc1.longitude__c + '.xml';
	    IncidentCouncilUpdater.isApexTest = true;
	    Test.startTest();
	    	IncidentCouncilUpdater.updateIncident(Inc1.ID);
	    Test.stopTest();
	}
	static testMethod void testFutureCallFail(){
	    Incident__c Inc1 = new Incident__c(name='Other', latitude__c='53.54489', longitude__c='-2.44467');
	    insert Inc1;
	    String StrEndPoint = 'http://www.uk-postcodes.com/latlng/' + Inc1.latitude__c + ',' + Inc1.longitude__c + '.xml';
	    IncidentCouncilUpdater.isApexTest = false;
	    Test.startTest();
	    	IncidentCouncilUpdater.updateIncident(Inc1.ID);
	    Test.stopTest();
	}
	
	static testMethod void testgetResponseBody() {
	    Incident__c Inc1 = new Incident__c(name='Other', latitude__c='53.54489', longitude__c='-2.44467');
	    insert Inc1;
	    IncidentCouncilUpdater i= new IncidentCouncilUpdater();
	    String StrEndPoint = 'http://www.uk-postcodes.com/latlng/' + Inc1.latitude__c + ',' + Inc1.longitude__c + '.xml';
	    IncidentCouncilUpdater.isApexTest = false;
	    String path = Inc1.latitude__c + ',' + Inc1.longitude__c;
	    
	    Test.startTest();
	    	HttpResponse r = new HttpResponse();
		    HttpRequest ireq = i.createRequest('GET', '' + path);
	    	i.getResponseBody(r, ireq);
	    Test.stopTest();
	}

}

 

 

As stated above, I tested this in my Developers account and it works fine. I actually copied your trigger and created your Incident object to test.  When I created a new incident record, the trigger calls the future call which retrieves the data from the webservice and then updates the newly created Incident record.

 

Hope this helps!

This was selected as the best answer
LooseLipsLooseLips

:smileysurprised:

 

Smills - that is way beyond the call of duty!!!!!!

 

I cannot thank you enough for the time and effort you have put in here, it's extremely impressive. I will get this tested ASAP although I'm sure it looks good.

 

I'll get this click fixed as soon as I get it into test.

LooseLipsLooseLips

94%!!!!

 

Unbelievable - that structure should help me immensely with my next projects, Smills!!!

smillssmills

Happy to have helped! I am still learning new things everyday!

 

Like I stated in my first email, I gained the knowledge from the articles linked above and tailored them for my project.  The main article I used was Virtual Callout Testing.  So alot of credit has to go to Simon Fell and Dave Carroll for posting that guide.  Also, Scott Hammetter's guide in Testing HTTP Callouts gave me insight on how to bypass items with the isApexTest variable that couldn't be tested. 

 

So thank them also!