0

guys!

I have a problem with one method in my Apex class, which I need to cover by tests. This class uses "GET" callout and checks, if the input field is empty (null). If it is, the @AuraEnabled method pulls value from a specific custom object field, but I can't see, how do you test such thing. Also, I'm quite a newbie, so it makes things harder :). Here is my code:

Apex class:

public with sharing class MyWeatherCallout {
public static Httpresponse GetWeatherCallout(String city) {
    Http Http = new Http();
    HttpRequest request = new HttpRequest();
    request.setEndpoint('http://api.openweathermap.org/data/2.5/weather?APPID=4452fe32937db97f4ba988929a52290e&q=' + city + '&units=metric');
    request.setMethod('GET');
    HttpResponse response = Http.send(request);
    return response;

}
@AuraEnabled
public static String getjson(String city) {
    System.debug(city);
    if (city == null || city== '') {
        id profileid = UserInfo.getProfileId();
        User User = [select city from User where profileid =: profileid];
        city = User.city;

        if (city == null || city == '') {
            Default_City__c defobj = [Select Default_City_Field__c from Default_City__c];
            city = defobj.Default_City_Field__c;

        }
    }
    String mystring = GetWeatherCallout(city).getBody();
    System.debug(mystring);
    return mystring;
}

Test class:

    @isTest
private class MyWeatherTestClass {
    @isTest
    static void testGetCallout() {
        StaticResourceCalloutMock mock = new 
        StaticResourceCalloutMock();
        mock.setStaticResource('OpenWeatherMap');
        mock.setStatusCode(200);
        mock.setHeader('Content-Type', 'application/json;charset=UTF-8');
        Test.setMock(HttpCalloutMock.class, mock);
        HttpResponse result = 
        MyWeatherCallout.GetWeatherCallout('Brest');
        System.assertNotEquals(null,result,
            'The callout returned a null response.');
        System.assertEquals(200,result.getStatusCode(),
          'The status code is not 200.');
        System.assertEquals('application/json;charset=UTF-8',
          result.getHeader('Content-Type'),
          'The content type value is not expected.');

    }
    static testMethod void test_getjson_UseCase1(){
    List<Default_City__c> default_city_Obj  =  [SELECT Default_City_Field__c from Default_City__c];
    System.assertEquals(true,default_city_Obj.size()>0);
    MyWeatherCallout obj01 = new MyWeatherCallout();
    MyWeatherCallout.getjson('test data');
  }
}

1 Answer 1

0

First of all in your MyWeatherCallout class you should add a limit 1 on your query :
Default_City__c defobj = [Select Default_City_Field__c from Default_City__c limit 1];
Otherwise if you have more than one record saved in your instance for this object you'll get a runtime error.
If your custom object Default_City__c is not intended to store more than one record, you should even use a static resource instead.


Next thing, your code

    id profileid = UserInfo.getProfileId();
    User User = [select city from User where profileid =: profileid];

should be

    Id userId =  UserInfo.getUserId();
    User User = [select city from User where Id = :userId limit 1];

or you might return a city of another user having the same profile.


Now obviously you cannot test internal behavior of your code if you call a mock that returns always the same value because... it will return the same value no matter what happens in your code !

If you want to actually test the logic of the fallback city assignment, you have to use a mock that checks the endpoint value :

Let's write this mock so that it checks any possible case :

global class MyWeatherMock implements HttpCalloutMock {
    global HTTPResponse respond(HTTPRequest req) {
        String endpoint = req.getEndpoint();
        //check if query is empty :
        Boolean isEmpty = Pattern.matches('.*&q=&units=metric$', endpoint);
        //check if query is the default city 
        Default_City__c  default_city_Obj =  [SELECT Default_City_Field__c from Default_City__c limit 1];
        Boolean isDefault = Pattern.matches('.*&q='+ default_city_Obj.default_city_field__c +'&units=metric$', endpoint);
        //check if query is user city
        Boolean isUser = Pattern.matches('.*&q=Rennes&units=metric$', endpoint);

        HttpResponse res = new HttpResponse();
        res.setHeader('Content-Type', 'application/json');
        if (isEmpty) res.setBody('{"empty":true, "default": false, "user":false}');
        else if (isDefault) res.setBody('{"empty":false, "default": true, "user":false}');
        else if (isUser) res.setBody('{"empty":false, "default": false, "user":true}');
        else res.setBody('{"empty":false, "default":false, "user":false}');

        res.setStatusCode(200);
        return res;
    }
}

Now the test is

@isTest
private class MyWeatherMockedTestClass {
    static {
        Test.setMock(HttpCalloutMock.class, new MyWeatherMock());  
        Default_city__c def = new Default_city__c(Default_city_field__c='Quimper');
        insert def;

        Profile p = [SELECT Id FROM Profile WHERE Name='Standard User']; 
        User user = new User(Alias = 'ker', FirstName='Quentin', LastName='KerApex', 
                             email='[email protected]', username='[email protected]', City='Rennes',
                             EmailEncodingKey='UTF-8',LanguageLocaleKey='fr', 
                            LocaleSidKey='fr_FR', ProfileId = p.Id, 
                            TimeZoneSidKey='Europe/Paris' );
        insert user;
    }
    @isTest
    static void testGetCallout() {
        Test.startTest();
        //with data
        String result = MyWeatherCallout.getjson('Brest');
        Map<String, Object> obj = (Map<String, Object>) JSON.deserializeUntyped(result);
        System.assertEquals(obj.get('empty'), false);
        System.assertEquals(obj.get('default'), false);

        //with empty string
        result = MyWeatherCallout.getjson('');
        obj = (Map<String, Object>) JSON.deserializeUntyped(result);
        System.debug(obj);
        System.assertEquals(obj.get('empty'), false);
        System.assertEquals(obj.get('default'), true);
        System.assertEquals(obj.get('user'), false);

        User user = [Select Id from User Where LastName='KerApex' and City='Rennes'limit 1];
        System.runAs(user){
            result = MyWeatherCallout.getjson('');
            obj = (Map<String, Object>) JSON.deserializeUntyped(result);
            System.assertEquals(obj.get('empty'), false);
            System.assertEquals(obj.get('default'), false);
            System.assertEquals(obj.get('user'), true);
        }

        //answer should never be empty:true
        Test.stopTest();
    }
}

This way you check that the value sent to your webservice is the default one (here Quimper) when you call the function with an empty string, unless the current user has a city specified on his profile, in which case the value sent is this city.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .