+ Start a Discussion
Abhiram Sheshadri 9Abhiram Sheshadri 9 

Apex REST callouts trailhead challenge giving System.Nullpointer exception, Please help

Hi,

I have written the below classes as part of the trailhead challenge for Apex REST callouts.

The class -

public class AnimalLocator {
  
  public static String getAnimalNameById(Integer id) {
    
    Http http = new Http();
    HttpRequest request = new HttpRequest();
    request.setEndpoint('https://th-apex-http-callout.herokuapp.com/animals/'+id);
    request.setMethod('GET');
    
    HttpResponse response = http.send(request);
    List<Object> animals; 
    String returnValue; 
    
    // parse the JSON response
    if (response.getStatusCode() == 200) {
      Map<String, Object> result = (Map<String, Object>) JSON.deserializeUntyped(response.getBody());
      animals = (List<Object>) result.get('animals');
      System.debug(animals);
    }
    
    if (animals.size() > 0 && animals != NULL && id < animals.size()) {
      returnValue = (String) animals.get(id);
    }
    
    return returnValue;
  } 
    
}

Mock Response Class - 

@isTest
global class AnimalLocatorMock implements HttpCalloutMock {
     // Implement this interface method
    global HTTPResponse respond(HTTPRequest request) {
        // Create a fake response
        HttpResponse response = new HttpResponse();
        response.setHeader('Content-Type', 'application/json');
        response.setBody('{"animals": ["majestic badger", "fluffy bunny", "scary bear", "chicken", "mighty moose"]}');
        response.setStatusCode(200);
        return response; 
    }
}

Test Class - 

@isTest
private class AnimalLocatorTest{
    @isTest static void AnimalLocatorMock1() {
        Test.setMock(HttpCalloutMock.class, new AnimalLocatorMock());
        string result = AnimalLocator.getAnimalNameById(3);
        String expectedResult = 'chicken';
        System.assertEquals(result,expectedResult );
    }
}

I have got 100% code coverage for the main class. But when I check the challenge I get 

Challenge Not yet complete... here's what's wrong: 
There was an unexpected error in your org which is preventing this assessment check from completing: System.NullPointerException: Attempt to de-reference a null object

Please tell me if any changes to the code is required. It's really frustrating as I am stuck from past 3-4 days with this unit.

Thanks & Regards,

Abhiram Sheshadri
Best Answer chosen by Abhiram Sheshadri 9
Uvais KomathUvais Komath
public class AnimalLocator{
    public static String getAnimalNameById(Integer x){
        Http http = new Http();
        HttpRequest req = new HttpRequest();
        req.setEndpoint('https://th-apex-http-callout.herokuapp.com/animals/' + x);
        req.setMethod('GET');
        
        HttpResponse res = http.send(req);
            if (response.getStatusCode() == 200) {
        Map<String, Object> results = (Map<String, Object>)JSON.deserializeUntyped(res.getBody());
        Map<String, Object> animal = (Map<String, Object>) results.get('animal');
        return (String)animal.get('name');

}
    }
}
works fine for me
 

All Answers

Uvais KomathUvais Komath

Hi, Did you click "Run all"

 

Uvais KomathUvais Komath
public class AnimalLocator{
    public static String getAnimalNameById(Integer x){
        Http http = new Http();
        HttpRequest req = new HttpRequest();
        req.setEndpoint('https://th-apex-http-callout.herokuapp.com/animals/' + x);
        req.setMethod('GET');
        
        HttpResponse res = http.send(req);
            if (response.getStatusCode() == 200) {
        Map<String, Object> results = (Map<String, Object>)JSON.deserializeUntyped(res.getBody());
        Map<String, Object> animal = (Map<String, Object>) results.get('animal');
        return (String)animal.get('name');

}
    }
}
works fine for me
 
This was selected as the best answer
Abhiram Sheshadri 9Abhiram Sheshadri 9
Hi Uvais,

Yeah, I clicked on "Run All". And can you post your mock response as well as test class here, so that I can understand how you solved it.
Uvais KomathUvais Komath
rest same, only the animallocator is different
Uvais KomathUvais Komath

Try replacing the animal locator.

Keep the other 2 same.

Run All

 

And check the challenge again

Abhiram Sheshadri 9Abhiram Sheshadri 9
I replaced my animal locator with yours,
Got the below error. 
Error: Compile Error: Non-void method might not return a value or might have statement after a return statement. at line 9 column 13.

Is it the same class which you used for completing the challenge?
 
Uvais KomathUvais Komath
Yes its the same!
Abhiram Sheshadri 9Abhiram Sheshadri 9
Thanks Uvais, Changed the code a little bit. It worked and passed the challenge.
Shailendra Singh 21Shailendra Singh 21
HI Abhiram,
I have the same issue. What change u did to fix this issue ? 
Abhiram Sheshadri 9Abhiram Sheshadri 9
Hi Shailendra,

I changed the code a little bit.You can try the below code.
 
public class AnimalLocator{
    public static String getAnimalNameById(Integer x){
        Http http = new Http();
        HttpRequest req = new HttpRequest();
        req.setEndpoint('https://th-apex-http-callout.herokuapp.com/animals/' + x);
        req.setMethod('GET');
        Map<String, Object> animal= new Map<String, Object>();
        HttpResponse res = http.send(req);
            if (res.getStatusCode() == 200) {
        Map<String, Object> results = (Map<String, Object>)JSON.deserializeUntyped(res.getBody());
      animal = (Map<String, Object>) results.get('animal');
        }
return (String)animal.get('name');
    }
}

 
Abhilash M 2Abhilash M 2
i got the below error


Executing the 'getAnimalNameById' method on 'AnimalLocator' failed. Make sure the method exists with the name 'getAnimalNameById', is public and static, accepts an Integer and returns a String.
Uvais KomathUvais Komath
Mind sharing your code Abhilash M 2?
manoj krishnamanoj krishna
Modify the AnimalLocatorMock mock class to below. 
@isTest
global class AnimalLocatorMock implements HttpCalloutMock {
    // Implement this interface method
    global HTTPResponse respond(HTTPRequest request) {
        // Create a fake response
        HttpResponse response = new HttpResponse();
        response.setHeader('Content-Type', 'application/json');
        response.setBody('{"animal":{"id":1,"name":"chicken","eats":"chicken food","says":"cluck cluck"}}');
        response.setStatusCode(200);
        return response; 
    }
}
manoj krishnamanoj krishna
Response set in your mock class is the reponse of the post method.that is the reason you are getting null pointer exception
VamsiVamsi
Hi Could someone please help me, I keep getting the error variable doesn't exists result.

public class AnimalLocator {

public static string getAnimalNameById (integer i)
{
    Http ht = new Http();
        HttpRequest request = new HttpRequest();
        request.setEndpoint('https://th-apex-http-callout.herokuapp.com/animals/' + i);
        request.setMethod('GET');
        HttpResponse response = ht.send(request);
        // If the request is successful, parse the JSON response.
    if (response.getStatusCode() == 200) 
            Map<String, Object> result = (Map<String, Object>)JSON.deserializeUntyped(response.getBody());
             Map<string,object> cc = (Map<string,object>) result.get('animals');
       return (string) cc.get('name');
       
  }
}
manoj krishnamanoj krishna
Can you give more detail about error,which line it is throwing the error
VamsiVamsi
Hi Manoj,

I guess at this line 

Map<String, Object> result = (Map<String, Object>)JSON.deserializeUntyped(response.getBody());


 Error : variable doesn't exists result.
 
manoj krishnamanoj krishna

if (response.getStatusCode() == 200) 
            Map<String, Object> result = (Map<String, Object>)JSON.deserializeUntyped(response.getBody());
             Map<string,object> cc = (Map<string,object>) result.get('animals');

u have not used braces after if condition. So technically only result variable is inside if statement. with local scope. it is not visible outside the if statement.
Correct it as below
 if (response.getStatusCode() == 200) 
{
            Map<String, Object> result = (Map<String, Object>)JSON.deserializeUntyped(response.getBody());
             Map<string,object> cc = (Map<string,object>) result.get('animals');
}
VamsiVamsi
Thanks Manoj, It worked and modified some code after adding braces.
Bhanu ErraguntlaBhanu Erraguntla
Abhiram / Uvais
I am getting the null pointer exception. My code is similar to that as above. Getting the error as below. 
"Challenge Not yet complete... here's what's wrong: 
There was an unexpected error in your org which is preventing this assessment check from completing: System.NullPointerException: Attempt to de-reference a null object"  What has fixed the null pointer exception please?
Thanks
Bhanu
Abhiram Sheshadri 9Abhiram Sheshadri 9
Hi Bhanu,

Please post your code here so that we can take a look at the issue.

Thanks,
Abhiram
michelle emanuel 59michelle emanuel 59
I got the same problem: Challenge Not yet complete... here's what's wrong:
There was an unexpected error in your org which is preventing this assessment check from completing: System.NullPointerException: Attempt to de-reference a null object  when I went to verify my code. I did verify that I get 100% code coverage and I did verify that everthing worked properly but no matter what I do I still get the same error when I do check challenge
 
Bhanu ErraguntlaBhanu Erraguntla
Hello Abhiram
Here are the classes

public class AnimalLocator {

    public static String getAnimalNameById(Integer idVal) {
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        request.setEndpoint('https://th-apex-http-callout.herokuapp.com/animals/'+idVal);
        
        String resultValue =NULL; 
        List<Object> animals;
        
        request.setMethod('GET');
        HttpResponse response = new HttpResponse();
        response = http.send(request);
        // If the request is successful, parse the JSON response.

        if (response.getStatusCode() == 200) {
            // Deserializes the JSON string into collections of primitive data types.
            Map<String, Object> results = (Map<String, Object>) JSON.deserializeUntyped(response.getBody());
            animals = (List<Object>) results.get('animals');
            System.debug(animals);

           if (animals.size() > 0 && animals != NULL && idVal < animals.size()) {
                  resultValue = (String) animals.get(idVal);
           }         
        }
        return resultValue;  
    }
}

-------------------
@isTest
private class AnimalLocatorTest {
    
    @isTest static void testgetAnimalNameById() {
        
        Test.setMock(HttpCalloutMock.class, new AnimalLocatorMock());     
        String result = '';
        result = AnimalLocator.getAnimalNameById(2);
         
        System.assertEquals('scary bear',result, 'The animals are same.');
    }
}
------------------------
@IsTest
global class AnimalLocatorMock implements HttpCalloutMock {
    //Implement this interface method
    global HTTPResponse respond(HTTPRequest request) {
        // Create a fake response
        HttpResponse response = new HttpResponse();
        response.setHeader('Content-Type', 'application/json');
        response.setBody('{"animals": ["majestic badger", "fluffy bunny", "scary bear", "chicken", "mighty moose"]}');
        response.setStatusCode(200);
        return response;
    }
}

Please suggest.
Thanks
Bhanu
michelle emanuel 59michelle emanuel 59
My code is not the same but similar and I get the same error message.  I did try a few other ways of organizing my code and found I got the same response when checking the answer.
manoj krishnamanoj krishna

Guys who ever got 100% code coverage and still challenge not complete ,check your httpmock callout class,check if it is like below ,the json response.if not change it and let me know
@isTest
global class AnimalLocatorMock implements HttpCalloutMock {
    // Implement this interface method
    global HTTPResponse respond(HTTPRequest request) {
        // Create a fake response
        HttpResponse response = new HttpResponse();
        response.setHeader('Content-Type', 'application/json');
        response.setBody('{"animal":{"id":1,"name":"chicken","eats":"chicken food","says":"cluck cluck"}}');
        response.setStatusCode(200);
        return response; 
    }
}

 
manoj krishnamanoj krishna
If you check the response of the end point url https://th-apex-http-callout.herokuapp.com/animals/1
 is 
{"animal":{"id":1,"name":"chicken","eats":"chicken food","says":"cluck cluck"}}

So we have to change the httpmock callout class to give the above response.

 
michelle emanuel 59michelle emanuel 59
The code above gives the null pointer when executing the test. the code below works but does not pass the verification from trailhead.
// Create a fake response
        		response.setHeader('Content-Type', 'application/json');
          		response.setBody('{"animals": ["majestic badger", "fluffy bunny", "scary bear", "chicken", "mighty moose"]}');
        		response.setStatusCode(200);
        		return(response);

 
manoj krishnamanoj krishna
@michelle
Modify the test class like below
@isTest
public class AnimalLocatorTest {
  @isTest public static void AnimalLocatorMock() {
       Test.setMock(HttpCalloutMock.class, new AnimalLocatorMock());
        string result = AnimalLocator.getAnimalNameById(1);
      system.debug(result);
        String expectedResult = 'chicken';
        System.assertEquals(result,expectedResult );
    }
}
Mock class
@isTest
global class AnimalLocatorMock implements HttpCalloutMock {
    // Implement this interface method
    global HTTPResponse respond(HTTPRequest request) {
        // Create a fake response
        HttpResponse response = new HttpResponse();
        response.setHeader('Content-Type', 'application/json');
        response.setBody('{"animal":{"id":1,"name":"chicken","eats":"chicken food","says":"cluck cluck"}}');
        response.setStatusCode(200);
        return response; 
    }
}

Animal Locator class
public class AnimalLocator
{

  public static String getAnimalNameById(Integer id)
   {
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        request.setEndpoint('https://th-apex-http-callout.herokuapp.com/animals/'+id);
        request.setMethod('GET');
        HttpResponse response = http.send(request);
          String strResp = '';
           system.debug('******response '+response.getStatusCode());
           system.debug('******response '+response.getBody());
        // If the request is successful, parse the JSON response.
        if (response.getStatusCode() == 200) 
        {
            // Deserializes the JSON string into collections of primitive data types.
           Map<String, Object> results = (Map<String, Object>) JSON.deserializeUntyped(response.getBody());
            // Cast the values in the 'animals' key as a list
           Map<string,object> animals = (map<string,object>) results.get('animal');
            System.debug('Received the following animals:' + animals );
            strResp = string.valueof(animals.get('name'));
            System.debug('strResp >>>>>>' + strResp );
        }
        return strResp ;
   }
  
}

For the above code,challenge will get cleared.
 
michelle emanuel 59michelle emanuel 59
it worked but the code I did worked as well without errors the trailhead should not be as sensitive and if you get coverage and no warnings it should pass.
Bhanu ErraguntlaBhanu Erraguntla
Manoj / Abhiram
Thanks for your responses.  It finally worked for me.  Was making a few mistakes.

In AnimalLocator I coded as

 animals = (List<Object>) results.get('animals');

which was returning null.  Actually checked the debugger and found it.

corrected as

 animals = (List<Object>) results.get('animal');.

Next the statement
if (animals.size() > 0 && animals != NULL && idVal < animals.size()) {

was failing.  Not using the right way to check.  For the trailhead purpose, commenting it sufficed

Next I decided which Id to search for and used that

In the mock class
replaced

   response.setBody('{"animals": ["majestic badger", "fluffy bunny", "scary bear", "chicken", "mighty moose"]}');

with
response.setBody('{"animal":{"id":1,"name":"chicken","eats":"chicken food","says":"cluck cluck"}}');

Made suitable changes in the test class as below

result = AnimalLocator.getAnimalNameById(1);
         
        System.assertEquals('chicken',result, 'The animals are same.');
---
And ran the test.  No errors and exceptions. 100% code coverage achieved.  Trailhead test cleared :-)

Thanks
Bhanu
Sudipta MondalSudipta Mondal
I got this error message :
Challenge Not yet complete... here's what's wrong: 
There was an unexpected error in your org which is preventing this assessment check from completing: System.CalloutException: Unauthorized endpoint, please check Setup->Security->Remote site settings. endpoint = https://th-apex-http-callout.herokuapp.com/animals/99
Abhiram Sheshadri 9Abhiram Sheshadri 9
Hi Sudipta,

Can you please post your code here so that we can check what the issue is?

And have you set the remote site settings properly? Is the endpoint effective ?

Thanks,
Abhiram
Sudipta MondalSudipta Mondal
Hi Abhiram,
My remote site setting not set properly.So i got the error.
Now This is ok.
Thanks,
Sudipta
Jeff HansenJeff Hansen
Thank you manoj and michelle, if it wasn't for this form page i dont think i could have passed this challenge.This developer intermediate trail, i think the chanllenges have gotten more difficult then what the text goes over, and with out this form i dont think many of the non super advanced developers can pass them easily...
Suhas GBSuhas GB
Hi In AnimalLocatorTest i.e in test class I'm getting a error i.e. Error: Compile Error: Method does not exist or incorrect signature: AnimalLocator.getAnimalNameById(Integer).

error is for this line in code. i.e.  string result = AnimalLocator.getAnimalNameById(3);  
Anuja Patil 10Anuja Patil 10
Hi, 
I am getting the below error for the animal locator class:

For the line :animals = (Map<String,Object>) result.get('animal');
Error :Illegal Assignment from map to map.

Can anyone assist? 

Regards,
Anuja
Amit SahooAmit Sahoo
In my case, I still could not find out what is the issues : here are my classes : 

AnimalLocator:
public class AnimalLocator{
    public static String getAnimalNameById(Integer x){
        Http http = new Http();
        HttpRequest req = new HttpRequest();
        req.setEndpoint('https://th-apex-http-callout.herokuapp.com/animals/' + x);
        req.setMethod('GET');
        HttpResponse res = http.send(req);
        
        if (res.getStatusCode() == 200) {
            Map<String, Object> results = (Map<String, Object>)JSON.deserializeUntyped(res.getBody());
            List<Object> animals = (List<Object>) results.get('animals');
            if(animals != null){
                for ( Object animal :  animals){
                   Map<String, Object> animalMap = (Map<String, Object>) animal;
                   if(animalMap.get('id') == x){
                       return (String) animalMap.get('name');
                   }
                }
            }
		}
        return null;
    }
}

AnimalLocatorMock
@isTest
global class AnimalLocatorMock implements HttpCalloutMock {
    global HttpResponse respond(HttpRequest request){
        HttpResponse response = new HttpResponse();
        response.setHeader('Content-Type', 'application/json');
        response.setBody('{"animals":[{"id":12345,"name":"majestic badger"},{"id":12346,"name":"fluffy bunny"},{"id":12347,"name":"cheeky Chicken"}]}');
        response.setStatusCode(200);
        return response;
    }
}

And my AnimalLocatorTest :
 
@isTest
private class AnimalLocatorTest {
    @isTest static void testLocaterCallout(){
        Test.setMock(HttpCalloutMock.class, new AnimalLocatorMock());
        String animalName = AnimalLocator.getAnimalNameById(12345);
        system.assertEquals('majestic badger', animalName);
    }  
    @isTest static void testNullAnimalCallout(){
        Test.setMock(HttpCalloutMock.class, new AnimalLocatorMock());
        String animalName = AnimalLocator.getAnimalNameById(123433);
        system.assertEquals(NULL, animalName);
      }   
}

I do not get any error in my Test Run , but when I submit I get this error : 

Challenge Not yet complete... here's what's wrong: 
Executing the 'getAnimalNameById' method on 'AnimalLocator' failed. Make sure the method exists with the name 'getAnimalNameById', is public and static, accepts an Integer and returns a String.

Can anybody please help 
Thanks
 
Mike ArthurMike Arthur
Hi Amit, It took me a little longer than 40 mins too! What you have is pretty similar to what I have, which passed. Rather than post the solution here, send an email to mike at mikearthur dot net and I’ll send you what I have so that you can figure out where it’s different. Thanks, Mike.
Venkatesh Kumar SakthivelVenkatesh Kumar Sakthivel
@Amit Sahoo
Hi,
You have to return the animal name in your apex code, but i can see that you are returning null value. Kindly check the code once and try the challenge again.

Thanks
Venkatesh
Sidney Rodrigues AdmSidney Rodrigues Adm
Hi,
With 100% code coverage for the main class and presenting the error below:

Challenge Not yet complete ... here's what's wrong:
There was an error in your org which is preventing this assessment check from completing: System.NullPointerException: Attempt to de-reference to null object

I solved with comment of @Sudipta Mondal, where he comments that he had not configured the remote site correctly.
My solution was to select the "Disable Protocol Security" option under Setup -> Remote Sites Settings for the site https://th-apex-http-callout.herokuapp.com
BINOY MATHEWBINOY MATHEW
I wasted so much time on this. Hence feel the need to put my answer which worked for me. I know for sure that it will help someone not loose hair or waste time. Challenge threw error - 'The Apex test class AnimalLocatorTest does not appear to be using the AnimalLocatorMock class correctly'.

First Register the url in the Remote site settings.

Please try this code if other options fail-

animal locator test
==============

@isTest
private class AnimalLocatorTest{
    @isTest
    static void testAnimalNameById(){
        // Set mock callout class
        Test.setMock(HttpCalloutMock.class, new AnimalLocatorMock());
        // This causes a fake response to be sent
        // from the class that implements HttpCalloutMock.
        String result = AnimalLocator.getAnimalNameById(1);
        
        // Verify mock response is not null
        System.assertNotEquals(null,result,'The callout returned a null response.');
        // Verify status code
        System.assertEquals('tiger',result);
    }
}

------------------------------
animal locator mock

@isTest
global class AnimalLocatorMock implements HttpCalloutMock {
    // Implement this interface method
    global HTTPResponse respond(HTTPRequest request) {
        // Create a fake response
        HttpResponse response = new HttpResponse();
        response.setHeader('Content-Type', 'application/json');
        response.setBody('{"animal":{"id":1,"name":"tiger","eats":"dear","says":"grow"}}');
        response.setStatusCode(200);
        return response; 
    }
}
----------------------
animal locator

public class AnimalLocator{
    public static String getAnimalNameById(Integer idAsParam){
        String retVal = null;
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        request.setEndpoint('https://th-apex-http-callout.herokuapp.com/animals/'+idAsParam);
        request.setMethod('GET');
        HttpResponse response = http.send(request);

        if (response.getStatusCode() == 200) {
            Map<String, Object> results = (Map<String, Object>) JSON.deserializeUntyped(response.getBody());
            Map<string,object> mapOfAnimals = (map<string,object>) results.get('animal');

            retVal = string.valueof(mapOfAnimals.get('name'));
        }
        
        return retVal;
    }
}
Sujogya PadhiSujogya Padhi
Thanks @Binoy Mathew. The code that you posted works just fine. Took me more than an hour to figure out whats wrong. Then I realized that I have been using my Variable with name 'Id' which is also a data type. :-p
venky klkrnvenky klkrn
Thanks @Binoy, It worked 
Nikunj GangradeNikunj Gangrade

public class AnimalLocator {
    public static String getAnimalNameById(Integer id)
    {
        String animalName;
        System.debug('ID is'+id);
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        request.setEndpoint('https://th-apex-http-callout.herokuapp.com/animals/'+id);
        request.setMethod('GET');
        HttpResponse response = http.send(request);
        
        if (response.getStatusCode() == 200) {
            // Deserializes the JSON string into collections of primitive data types.
             Map<String, Object> results = (Map<String, Object>) JSON.deserializeUntyped(response.getBody());
             Map<String, Object> animal = (Map<String, Object>) results.get('animal');
             animalName=(String)animal.get('name');

        }
        System.debug(''+animalName);
        return animalName;
    }

}

 

This worked fine for me