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
saran kumar 9saran kumar 9 

Apex REST Callouts - Create an Apex class that calls a REST endpoint and write a test class

i have created
1.AnimalLocator User-added image



2.AnimalLocatorMock
User-added image

3.AnimalLocatorTest

User-added image


error i am getting

User-added image

please help me
Sampath KumarSampath Kumar
Hi Saram,

You need to add your end point in remote site settings.

Go to set up > Remote Site Settings > New

Enter your end point and save it.

Mark this as best answer if this resolves your query.

Regards
Sampath
saran kumar 9saran kumar 9
please tell me what is my end point .....i am new and confused .....could write all the code but
Sampath KumarSampath Kumar
Hi Saran,

Your end point is 'https://th-apex-http-callout.herokuapp.com/animals'

Mark this as best answer if this answers your query.

Regards
Sampath
saran kumar 9saran kumar 9
@sampth .........thanks a lot sampath garu .......can you please help me

https://developer.salesforce.com/trailhead/visualforce_mobile_salesforce1/visualforce_mobile_salesforce1_actions_global

The 'BusinessCard' page must display the current user's first name, last name, email, phone, and title information using the appropriate Visualforce global variables.
The page should have an input field to enter an email address and a 'Send' button that allows users to quickly email their contact information to others. Implementing this requirement is optional for passing this challenge.  

please i need code to this part .....
Harsh DodiyaHarsh Dodiya
Hello,

Error : 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
Class : AnimalLocator

public class AnimalLocator {
    public static string getAnimalNameById(Integer x){
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        request.setEndpoint('https://th-apex-http-callout.herokuapp.com/animals');
        request.setMethod('GET');
        Map<String, Object>animal= new Map<String,Object>();
        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());
            animal = (Map<String, Object>) results.get('animal');
        }
            return(String)animal.get('name');
    }
}

Class : AnimalLocatorTest

@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);
    }
}

Class : AnimalLocatorMock

@isTest
global class AnimalLocatorMock implements HttpCalloutMock {
    global HTTPResponse respond(HTTPRequest request) {
         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;
    }
}

Can some one help me here please.
ArenoAreno
Hi everyone this codes works so fine and I tackeled the unit.

Check this out. 

Code for AnimalLocator apex 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 ;
   }
  
}
Code for Test Class - AnimalLocatorTest
@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);
    }
}

Code for AnimalLocatorMock
@isTest
global class AnimalLocatorMock implements HttpCalloutMock {
    global HTTPResponse respond(HTTPRequest request) {
         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;
    }
}

Thanks,
Santhosh
Hector SosaHector Sosa
Hi, I'm using this sentence: strResp = string.valueof(animals.get('name')); 
but im getting this error message:
Method does not exist or incorrect signature: [List<Object>].get(String)
Is there another way to get the value of a List<Object> element?
Thanks in advance.
ArunaAruna
Hi ,

I am trying solve trailhead problem but I am getting below message .

Method does not exist or incorrect signature: Test.setMock(Type, AnimalLocatorMock) when I am trying to save test class


public class AnimalLocator {
    public static string getAnimalNameById(Integer animalId){
        Http http=new Http();
        HttpRequest req=new HttpRequest();
        req.setEndPoint('https://th-apex-http-callout.herokuapp.com/animals/' + animalId);
        req.setMethod('GET');
        HttpResponse res=http.send(req);
        Map<String,Object> animals = new Map<String,Object>();
        if (res.getStatusCode() == 200) {
            Map<String,Object> results = (Map<String,Object>)JSON.deserializeUntyped(res.getBody());
            animals = (Map<String,Object>)results.get('animal');
        }
       else{System.debug('The status code returned was not expected: ' + res.getStatusCode() + ' ' + res.getStatus());}
        return (string)animals.get('name');
    }
}
 
@isTest
global class AnimalLocatorMock implements HttpCalloutMock {
    global HttpResponse respond(HttpRequest request){
           HttpResponse response = new HttpResponse();
        response.setHeader('Content-Type', 'application/json');
        response.setBody('{"animal":{"id":1,"name":"chicken","eats":"chicken food","says":"cluck cluck"}}');
        //response.setBody('{"animal":{"id":1,"name":"chicken"}}');
        response.setStatusCode(200);
        return response;  
    }
}
@isTest
private class AnimalLocatorTest{

    @isTest static void AnimalsCalloutsTest() {
        Test.setMock(HttpCalloutMock.class, new AnimalLocatorMock());  
        String ALresult = AnimalLocator.getAnimalNameById(1);     
        String expectedValue = 'chicken'; 
        System.assertEquals(ALresult, expectedValue);
    }
}
Fernando ParraFernando Parra
I got the same error:

Method does not exist or incorrect signature: Test.setMock(Type, AnimalLocatorMock) when I am trying to save test class.


Can some one help me here please.
 
harshapriya mharshapriya m
hai Every one
 follow this steps to tackle the challenge

Step 1 : go to Remote site controllers in security control
               Enter External site url https://th-apex-http-callout.herokuapp.com/animals/:id
               save

step 2 : Apex class 
               
          User-added image
step 3 : test class
User-added image

User-added image

step 4  : Devloper console 
                 click on test : choose Asyncronous test
                      click on new run 
                      choose the Animal locator mock 
                                          animal locator test
 Run 

that all 
challenge is done
  
Paul F. AlbuquerquePaul F. Albuquerque
Hey, I really wasn't a fan of this question. It bothered me that it was asking that the method have an input, which was supposed to be the id number, but that this input essentially didnt do anything. You could essentially use any integer and the result would be the same. 

I decided to change up the JSON file a bit and make it a bit more challenging to write a code that actually made use of the input. I am still learning and would really appreciate some feedback on my code if anyone has any input.

Aso, please note that the code I am posting will result in 100% code coverage but WON'T complete the challenge. It was done stricktly by me as a learning excersise. 
 
public with sharing class AnimalLocator {
    public static String getAnimalNameById(Integer animalNameId) {
        String animalName = '';
        //New Http 'GET' Request
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        request.setEndpoint('https://th-apex-http-callout.herokuapp.com/animals/:id');
        request.setHeader('Content-Type', 'application/json;charset=UTF-8');
        request.setMethod('GET');
        //Get response
        HttpResponse response = Http.send(request);
        //Parse JSON from the response body
        JSONParser parser = JSON.createParser(response.getBody());
        while (parser.nextToken() != null) {
            // Read entire JSON object
            if (parser.getCurrentToken() == JSONToken.START_OBJECT) {
                AnimalLocator.AnimalList animalList = (AnimalLocator.AnimalList) parser.readValueAs(AnimalLocator.AnimalList.class);
                System.debug(animalList.animal.size());
                //Sort through the list of animals to find one with the matching ID
                //Set the animal name
                for (Integer i = 0; i < animalList.animal.size() ; i++) {
                    if (animalList.animal[i].id == animalNameId){
                        animalName = animalList.animal[i].name;
                        break;
                    } else{
                        animalName = 'Could not find an Animal with a matching ID';
                    }
                }

            }
        }
        return animalName;
    }

    public class AnimalList {
        public List<animal> animal; //This has to be the same name thats in the JSON file.
    }

    //animal Object Wrapper
    public class animal {
        public Integer id;
        public String name;
        public String eats;
        public String says;
    }

}
 
@isTest
global class AnimalLocatorMock implements HttpCalloutMock{
    global HttpResponse respond(HttpRequest request){
        //Create Fake Response
        HttpResponse response = new HttpResponse();
        response.setHeader('Content-Type', 'application/json;charset=UTF-8');
        response.setStatusCode(200);
        response.setBody(' {"animal":[{"id":1,"name":"Chicken","eats":"Grain","says":"Cluck"},{"id":2,"name":"Dog","eats":"Chicken","says":"Woof"}]} ');
        return response;
    }
}
 
@isTest
public with sharing class AnimalLocatorTest {
    @isTest
     static void testGetCallout() {
        Test.setMock(HttpCalloutMock.class, new AnimalLocatorMock());
        String result = AnimalLocator.getAnimalNameById(1);
        String expectedResult = 'Chicken';
        System.assertEquals(result,expectedResult);
        result = AnimalLocator.getAnimalNameById(4);
        expectedResult = 'Could not find an Animal with a matching ID';
        System.assertEquals(result,expectedResult);
    }
}

 
Shashank Gupta 96Shashank Gupta 96
If any one facing below error :

Method does not exist or incorrect signature: Test.setMock(Type, AnimalLocatorMock) when I am trying to save test class

Please check if in your org is there any class name 'test'. Delete that class or change the name. This will work.
Ankit WaliaAnkit Walia
Hi, Can someone explain whether we need to take getAnimalNamebyID argument as 3 or 1?
I suppose it should be three with Chicken as Expected results but when I ran with 3, it accepted the code and Tests were passed. Please help if you know.
Himanshu NimjeHimanshu Nimje
Please try Below code .

100% working.

Issue with Line :    request.setEndpoint('https://th-apex-http-callout.herokuapp.com/animals/' + id); 

 
Solution
public with sharing class AnimalLocator {
    public static String getAnimalNameById(Integer animalNameId) {
        String animalName = '';
        //New Http 'GET' Request
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        request.setEndpoint('https://th-apex-http-callout.herokuapp.com/animals/'+id);
        request.setHeader('Content-Type', 'application/json;charset=UTF-8');
        request.setMethod('GET');
        //Get response
        HttpResponse response = Http.send(request);
        //Parse JSON from the response body
        JSONParser parser = JSON.createParser(response.getBody());
        while (parser.nextToken() != null) {
            // Read entire JSON object
            if (parser.getCurrentToken() == JSONToken.START_OBJECT) {
                AnimalLocator.AnimalList animalList = (AnimalLocator.AnimalList) parser.readValueAs(AnimalLocator.AnimalList.class);
                System.debug(animalList.animal.size());
                //Sort through the list of animals to find one with the matching ID
                //Set the animal name
                for (Integer i = 0; i < animalList.animal.size() ; i++) {
                    if (animalList.animal[i].id == animalNameId){
                        animalName = animalList.animal[i].name;
                        break;
                    } else{
                        animalName = 'Could not find an Animal with a matching ID';
                    }
                }

            }
        }
        return animalName;
    }

    public class AnimalList {
        public List<animal> animal; //This has to be the same name thats in the JSON file.
    }

    //animal Object Wrapper
    public class animal {
        public Integer id;
        public String name;
        public String eats;
        public String says;
    }

}

@isTest
global class AnimalLocatorMock implements HttpCalloutMock{
    global HttpResponse respond(HttpRequest request){
        //Create Fake Response
        HttpResponse response = new HttpResponse();
        response.setHeader('Content-Type', 'application/json;charset=UTF-8');
        response.setStatusCode(200);
        response.setBody(' {"animal":[{"id":1,"name":"Chicken","eats":"Grain","says":"Cluck"},
        {"id":2,"name":"Dog","eats":"Chicken","says":"Woof"}]} ');
        return response;
    }
}

@isTest
public with sharing class AnimalLocatorTest {
    @isTest
     static void testGetCallout() {
        Test.setMock(HttpCalloutMock.class, new AnimalLocatorMock());
        String result = AnimalLocator.getAnimalNameById(1);
        String expectedResult = 'Chicken';
        System.assertEquals(result,expectedResult);
       }
}

Please Select this as Best Answer if working properly.
 
Thanks in Advance :)


 
gil shanigil shani
what is the meaning of the number 1 after the id in 
response.setBody(' {"animal":[{"id":1,"name":"Chicken","eats":"Grain","says":"Cluck"},?
Ankit Jain 2909Ankit Jain 2909
Below is the 100% working code:

Go to set up > Remote Site Settings > New
Remote Site Name = animals_http
Remote Site URL = https://th-apex-http-callout.herokuapp.com
Description = Trailhead animal service: HTTP
Click on Save (Screenshot is below)
User-added image

Code for 'AnimalLocator' Class
public class AnimalLocator {
    public static string getAnimalNameById(Integer animalId){
        Http http=new Http();
        HttpRequest req=new HttpRequest();
        req.setEndPoint('https://th-apex-http-callout.herokuapp.com/animals/' + animalId);
        req.setMethod('GET');
        HttpResponse res=http.send(req);
        Map<String,Object> animals = new Map<String,Object>();
        if (res.getStatusCode() == 200) {
            Map<String,Object> results = (Map<String,Object>)JSON.deserializeUntyped(res.getBody());
            animals = (Map<String,Object>)results.get('animal');
        }
       else{System.debug('The status code returned was not expected: ' + res.getStatusCode() + ' ' + res.getStatus());}
        return (string)animals.get('name');
    }
}
Code for 'AnimalLocatorMock' Class
@isTest
global class AnimalLocatorMock implements HttpCalloutMock {
    global HttpResponse respond(HttpRequest request){
           HttpResponse response = new HttpResponse();
        response.setHeader('Content-Type', 'application/json');
        response.setBody('{"animal":{"id":1,"name":"chicken","eats":"chicken food","says":"cluck cluck"}}');
        //response.setBody('{"animal":{"id":1,"name":"chicken"}}');
        response.setStatusCode(200);
        return response;  
    }
}
Code for 'AnimalLocatorTest' Class
@isTest
public with sharing class AnimalLocatorTest {
    @isTest
     static void testGetCallout() {
        Test.setMock(HttpCalloutMock.class, new AnimalLocatorMock());
        String result = AnimalLocator.getAnimalNameById(1);
        String expectedResult = 'Chicken';
        System.assertEquals(result,expectedResult);
        result = AnimalLocator.getAnimalNameById(4);
        expectedResult = 'Could not find an Animal with a matching ID';
        System.assertEquals(result,expectedResult);
    }
}

Now, Developer Console > Test > Run All (Overall coverage should 100%) 

Now Go to Trailhead module and click on 'Check Challenge'

User-added image

 
KapavariVenkatramanaKapavariVenkatramana

@Ankit Jain 2909 

WOrked Nice ly THanks a lot...

harsha vardhan vasa 9harsha vardhan vasa 9
Hi Frnds,
when i tried the same above code im getting below error:
 Invalid conversion from runtime type List<ANY> to Map<String,ANY>
FATAL_ERROR Class.AnimalLocator.getAnimalNameById: line 14, column 1
Code:
public class AnimalLocator {
    public static string getAnimalNameById(integer animalNameId){
        http h= new http();
        httprequest req= new httprequest();
        req.setEndpoint('https://th-apex-http-callout.herokuapp.com/animals/'+animalNameId);
        req.setmethod('GET');
        httpresponse res =h.send(req);
        String strResp = '';
      //  map<string,object> animals =new Map<String,Object>();
        //list<object> animals =new list<object>();
        if(res.getStatusCode() == 200){
            map<string,object> results = (map<string,object>) JSON.deserializeUntyped(res.getBody());
            system.debug(''+results);
          map<string,object>  animals =(map<string,object>) results.get('animal');
            system.debug(''+animals);
          strResp= string.valueof(animals.get('name')); 
        }else
        {System.debug('The status code returned was not expected: ' + res.getStatusCode() + ' ' + res.getStatus());}
        return strResp; 
    }
}

Mock test:
@isTest
global class AnimalLocatorMock implements HttpCalloutMock   {
    
    global HTTPResponse respond(HTTPRequest request){
        HttpResponse response = new HttpResponse();
        response.setHeader('Content-Type', 'application/json');
        response.setBody(' {"animal":[{"id":1,"name":"Chicken","eats":"Grain","says":"Cluck"},{"id":2,"name":"Dog","eats":"Chicken","says":"Woof"}]} ');
        response.setStatusCode(200);
        return response;
    }
}

Test Class:

@isTest
public with sharing class AnimalLocatorTest {

    @isTest 
    static void testGetCallout(){
        Test.setMock(HttpCalloutMock.class, new AnimalLocatorMock());
        String resul1t =AnimalLocator.getAnimalNameById(1);
        string expectedresult ='Chicken';
        System.assertEquals(resul1t,expectedResult);
        resul1t = AnimalLocator.getAnimalNameById(4);
        expectedResult = 'Could not find an Animal with a matching ID';
        System.assertEquals(resul1t,expectedResult);  

    }
}

Not able to understand where i went wrong.

Regards,
Harsha.
Vincenzo.BoellisVincenzo.Boellis

I didn't understand how this JSON was built in the AnimalLocatorMock class, could someone explain it to me? Thank you. 

 

'{"animal":{"id":1,"name":"chicken","eats":"chicken food","says":"cluck cluck"}}'

Rahul Kumar DeyRahul Kumar Dey
Hi, please try the following code below its just not only pass the challenge, get the actual animal name from 'animal' object and I put this to debug log. If its solve your problem, don't forgot to mark this as best answer. 

Step-1   
         AnimalLocator.apxc

public class AnimalLocator {
    /* Method to GET response from a web service */
    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);
        //If request successful Parse the response
        Map<String, Object> animals = new Map<String, Object>();
        if(response.getStatusCode() == 200){
            //Deserialize the JSON string into collection object
            Map<String, Object> results = (Map<String, Object>)JSON.deserializeUntyped(response.getBody());
            animals = (Map<String, Object>) results.get('animal'); 
            system.debug('Animal Object->>>>'+animals);
            system.debug('Animals Name->>>>'+animals.get('name'));
        }
        else{
            system.debug('The status code return was not expected'+response.getStatusCode());
        }
        return (string)animals.get('name');    
    }
}

Step-2
         AnimalLocatorMock.apxc

@isTest
global class AnimalLocatorMock implements HttpCalloutMock {
    //implement interface method 
    global HttpResponse respond(HttpRequest request){
        //Creating 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;
    }
}

Step-3
         AnimalLocatorTest.apxc

@isTest
public class AnimalLocatorTest {
    @isTest static void getAnimalNameByIdTest(){
        Test.setMock(HttpCalloutMock.class, new AnimalLocatorMock());
        string results = AnimalLocator.getAnimalNameById(1);
        string expectedResult = 'chicken';
        system.assertEquals(expectedResult, results);
        /*string results = AnimalLocator.getAnimalNameById(2);
        string expectedResult2 = 'duck';
        system.assertEquals(expectedResult2, results, 'This is not expected...');*/
    }
}

Step-4
         Click Run Test in the 'AnimalLocatorTest' class ----> Go to 'AnimalLocator' class ----> Click on Code Coverage dropdown ----> Select All Tests
-----> It will show you 100% Code Coverage.

Step-5
         After that 100% Code Coverage how do you verify that you actually get correct response or not. Simple, Go to Logs Tab in Developer Console ----> Double click the recent envocation class ----> Click Debug only check box ----> Now you can see the out put.


User-added image
 
Rahul Kumar DeyRahul Kumar Dey
@Vincenzo, first of all you need to know that there only single record pass through this JSON string. And this contains not only name it includes id, and others fields too. So it looks like- '{"animal":{"id":1,"name":"chicken","eats":"chicken food","says":"cluck cluck"}}'.
If you want to pass more than one records you need to array type inside JSON string like-
'{"animal":[{"id":1, "name":"test1", "says":"Hello",},{"id":2, "name":"test2", "says":"World"}]}';   in this case we pass list of records through JSON string.
For more information refer this resource- https://json2apex.herokuapp.com/
Hope it helps!! 
Alex Novikov 7Alex Novikov 7
Thank you @Rahul Kumar Dey
Rahul Kumar DeyRahul Kumar Dey
Your welcome @Alex
Sachin Fuse1Sachin Fuse1
@Harsh Dodia, just replace your endpoint with this https://th-apex-http-callout.herokuapp.com/animals/'+x, in your code are not using method Parameter at the end of the endpoint string that's why you were getting null pointer exception.
Tripti LakharaTripti Lakhara
Challenge not yet complete in Trailhead Playground 1
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.

@Areno 
i applied same code but i am getting this error.
Giulia AlbanoGiulia Albano
Even if it's been a long time, did someone fixed the error posted by @Tripti ? I've got the same problem
suna gunduzhevsuna gunduzhev
Hello, have you created remote sites? @Tripti