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
Akash DeokarAkash Deokar 

Stuck in Apex specialist superbadge(Challenge 5)

Hello team,
 
I have stuck in Apex specialist superbadge(Challenge 5), Please help me with the resolution. I have written class WarehouseCalloutService, which is getting executed without error if i called it from debug log But getting runtime error while running test class written for that class.
 
Getting Error :- FATAL_ERROR System.TypeException: Invalid conversion from runtime type Map<String,ANY> to List<ANY>
 
 
class:-WarehouseCalloutService
global with sharing class WarehouseCalloutService {
    
private static final String WAREHOUSE_URL = 'https://th-superbadge-apex.herokuapp.com/equipment';    
    @future (callout=true)
    public static void runWarehouseEquipmentSync() {
        //ToDo: complete this method to make the callout (using @future) to the
        //      REST endpoint and update equipment on hand.
        Http http = new Http();
        HttpRequest req  = new HttpRequest();
        req.setEndpoint(WAREHOUSE_URL);
        req.setMethod('GET');
        HttpResponse res = http.send(req);
        
        if(res.getStatusCode()==200){
            List<object> results = (List<object>)JSON.deserializeUntyped(res.getBody());
            system.debug(results);
            List<Product2> productlist = new List<Product2>();
            for(Object o : results){
                Map<string,Object> eqp = (Map<String,Object>)o;
                system.debug(eqp);
                Product2 equipment = new Product2();                
                equipment.Replacement_Part__c = (Boolean)eqp.get('replacement');
                equipment.Current_Inventory__c = (Decimal)eqp.get('quantity');
                equipment.Lifespan_Months__c = (Integer)eqp.get('lifespan');
                equipment.Maintenance_Cycle__c = (Integer)eqp.get('maintenanceperiod');
                equipment.Name = (String)eqp.get('name');
                equipment.Cost__c = (Integer)eqp.get('cost');
                equipment.ProductCode = (String)eqp.get('_id');
                equipment.Warehouse_SKU__c = (String)eqp.get('sku');
                productlist.add(equipment);
            }
            system.debug(productlist);
            upsert productlist;
        }
    }
}

 
Malika Pathak 9Malika Pathak 9
Hi Akash,

Try this:
public with sharing class WarehouseCalloutService {
    private static final String WAREHOUSE_URL = 'https://th-superbadge-apex.herokuapp.com/equipment';
    
    @future(callout=true)
    public static void runWarehouseEquipmentSync() {
        //ToDo: complete this method to make the callout (using @future) to the
        //      REST endpoint and update equipment on hand.
    
		
		HttpResponse response = getResponse(); 
        if(response.getStatusCode() == 200)
        {
            List<Product2> results = getProductList(response); //get list of products from Http callout response
            
            if(results.size() >0)
            upsert results Warehouse_SKU__c; //Upsert the products in your org based on the external ID SKU
        }
        
    }
        //Get the product list from the external link
        public static List<Product2> getProductList(HttpResponse response)
        {
            
            List<Object> externalProducts = (List<Object>) JSON.deserializeUntyped(response.getBody()); //desrialize the json response
            List<Product2> newProducts = new List<Product2>();
            
            for(Object p : externalProducts)
            {
                Map<String, Object> productMap = (Map<String, Object>) p;
                Product2 pr = new Product2();
            	//Map the fields in the response to the appropriate fields in the Equipment object
                pr.Replacement_Part__c = (Boolean)productMap.get('replacement');
                pr.Cost__c = (Integer)productMap.get('cost');
                pr.Current_Inventory__c = (Integer)productMap.get('quantity');
                pr.Lifespan_Months__c = (Integer)productMap.get('lifespan') ;
                pr.Maintenance_Cycle__c = (Integer)productMap.get('maintenanceperiod');
                pr.Warehouse_SKU__c = (String)productMap.get('sku');
                pr.ProductCode = (String)productMap.get('_id');
                pr.Name = (String)productMap.get('name');
                
            
                newProducts.add(pr);
            }
            
            return newProducts;
            
        }
        
        // Send Http GET request and receive Http response
    
    public static HttpResponse getResponse() {
        
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        request.setEndpoint(WAREHOUSE_URL);
        request.setMethod('GET');
        HttpResponse response = http.send(request);
        
        return response;
        
    }
    }
If you found this answer helpful, please mark it as the best answer to help others.
 
Rahul JogRahul Jog
Hello Malika, I have a similar problem but my code coverage is only 30%
Tried your method but code coverage has not changed.
It keeps telljng me to implement Queueable
Most part of WarehouseCalloutService is not executed.
Here are my following classes:

WarehouseCalloutServiceTest
:
@isTest
private class WarehouseCalloutServiceTest {   
    @isTest  
    static void testWareHouseCallout(){
        Test.startTest();
        // implement mock callout test here
        Test.setMock(HTTPCalloutMock.class, new WarehouseCalloutServiceMock());
        WarehouseCalloutService.runWarehouseSync();
        System.enqueueJob(new WarehouseCalloutService());
        Test.stopTest();
        System.assertEquals(1, [SELECT count() FROM Product2]);
    }     
}

WarehouseCalloutServiceMock:

@isTest
public class WarehouseCalloutServiceMock implements HttpCalloutMock
{
    // implement http mock callout
    public static HTTPResponse respond(HTTPRequest request) 
    {
        System.assertEquals('https://th-superbadge-apex.herokuapp.com/equipment'
                            , request.getEndpoint());
        System.assertEquals('GET', request.getMethod());
        // Create a fake response
        HttpResponse response = new HttpResponse();
        response.setHeader('Content-Type', 'application/json');
        response.setBody('{"_id":"55d66226726b611100aaf741","replacement":false,"quantity":5,"name":"Generator 1000 kW","maintenanceperiod":365,"lifespan":120,"cost":5000,"sku":"100003"}');
        response.setStatusCode(200);
        return response; 
    }
}

WarehouseCalloutService:

public with sharing class WarehouseCalloutService implements Queueable
{
    
    private static final String WAREHOUSE_URL = 'https://th-superbadge-apex.herokuapp.com/equipment';
    
    @future(callout=true)
    public static void runWarehouseSync() 
    {
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        request.setEndpoint(WAREHOUSE_URL);
        request.setMethod('GET');
        HttpResponse response = http.send(request);
        // If the request is successful, parse the JSON response.
        if (response.getStatusCode() == 200) 
        {
            List<Object> externalProducts = (List<Object>) JSON.deserializeUntyped(response.getBody());
           
// Below code is not covered in the test class
         List<Product2> newProducts = new List<Product2>();
            
            for(Object p : externalProducts)
            {
                Map<String, Object> productMap = (Map<String, Object>) p;
                Product2 pr = new Product2();
                pr.Replacement_Part__c = (Boolean)productMap.get('replacement');
                pr.Cost__c = (Integer)productMap.get('cost');
                pr.Current_Inventory__c = (Integer)productMap.get('quantity');
                pr.Lifespan_Months__c = (Integer)productMap.get('lifespan') ;
                pr.Maintenance_Cycle__c = (Integer)productMap.get('maintenanceperiod');
                pr.Warehouse_SKU__c = (String)productMap.get('sku');
                pr.ProductCode = (String)productMap.get('_id');
                pr.Name = (String)productMap.get('name');
                newProducts.add(pr);
            }
            if(newProducts.size() >0)
            {
                upsert newProducts; 
                System.debug('Your System has been synced with the Warehouse');
                System.debug(newProducts);
            }
        }  
        
    }
    public void execute(QueueableContext context)
    {
        runWarehouseSync();
    }
}

// not covered till here.


Kindly help me as I have been Trying to solve this issue since three days.

Errors received :
System.TypeException: Invalid conversion from runtime type Map&lt;String,ANY&gt; to List&lt;ANY&gt;
Stack trace:
Class.WarehouseCalloutService.runWarehouseSync: line 17, column 1