I am writing a simple api callout for Tsheets, and its working just fine, now when writing the test class, its failing on the line "object results = Meta.get('results')".
The error is: System.JSONException: Unexpected character ('y' (code 121)): expected a valid value (number, String, array, object, 'true', 'false' or 'null') at input location [1,2]
Here is the Apex Class:
public class TSheetsGetTimesheets {
public void getTimesheets(){
TSheetsLogin__c tc = TSheetsLogin__c.getorgdefaults();
string AuthToken = tc.OAuth_Token__c;
Date d = Date.today();
String ToDate = string.valueOf(d);
Date JobDate = tc.Last_Sync_Run__c;
String LastRun = string.valueOf(JobDate);
string EndPoint = 'https://rest.tsheets.com/api/v1/timesheets?start_date='+ LastRun +'&end_date='+ ToDate +'&on_the_clock=no&';
system.debug(EndPoint);
Http http = new Http();
HttpRequest req = new HttpRequest();
req.setHeader('Authorization', 'Bearer ' + AuthToken);
req.setMethod('GET');
req.setEndpoint(EndPoint);
HttpResponse res = http.send(req);
String JsonStr = res.getBody();
Map<String, Object> meta = (Map<String, Object>) JSON.deserializeUntyped(JsonStr);
object results = meta.get('results');
string s = json.serializepretty(results);
Map<String, Object> o = (Map<String, Object>) JSON.deserializeUntyped(s);
string s1 = json.serializepretty(o.get('timesheets'));
Map<String, Object> o1 = (Map<String, Object>) JSON.deserializeUntyped(s1);
Map<String,Map<String,Object>> mapTimesheets = new Map<String,Map<String,Object>>();
for(string thisTimesheetId : o1.keySet()){
string stringThisTimesheet = json.serializepretty(o1.get(thisTimesheetId));
Map<String, Object> mapThisTimesheet = (Map<String, Object>) JSON.deserializeUntyped(stringThisTimesheet);
mapTimesheets.put(thisTimesheetId,mapThisTimesheet);
//if(thisTimesheetId == '173162158'){
//
If(mapTimesheets.size() > 0 ) {
timesheetData tds = new timesheetData(mapTimesheets.get(thisTimesheetId));
TSheets_Time_Entry__c tse = new TSheets_Time_Entry__c();
tse.Time_Entry_ID__c = tds.timesheetId;
tse.User_ID__c = tds.userId;
tse.Name = tds.jobcodeId;
tse.Start__c = tds.startDatetime;
tse.End__c = tds.endDatetime;
tse.TSheetsDuration__c = tds.duration;
tse.Type__c = tds.type;
insert tse;
}
}
tc.Last_Sync_Run__c = d;
update tc;
}
public class timesheetData{
public string timesheetId;
public string userId;
public string jobcodeId;
public datetime startDatetime;
public datetime endDatetime;
public integer duration;
public string type;
public string notes;
public timesheetData(object o){
string serializedObject = json.serializepretty(o);
Map<String, Object> mapObject = (Map<String, Object>) JSON.deserializeUntyped(serializedObject);
timesheetId = string.valueOf(mapObject.get('id'));
userId = string.valueOf(mapObject.get('user_id'));
jobcodeId = string.valueOf(mapObject.get('jobcode_id'));
startDatetime = convertDateTime(string.valueOf(mapObject.get('start')));
endDatetime = convertDateTime(string.valueOf(mapObject.get('end')));
duration = integer.valueOf(mapObject.get('duration'));
type = string.valueOf(mapObject.get('type'));
notes = string.valueOf(mapObject.get('notes'));
}
}
public static Datetime convertDateTime(String s){
integer startYear = integer.valueof(s.mid(0,4));
integer startMonth = integer.valueof(s.mid(5,2));
integer startDay = integer.valueof(s.mid(8,2));
integer startHour = integer.valueof(s.mid(11,2));
integer startMin = integer.valueof(s.mid(14,2));
integer startSec = integer.valueof(s.mid(17,2));
Datetime convertedDateTime = Datetime.newInstance(startYear, startMonth, startDay, startHour, startMin, startSec);
return convertedDateTime;
}
}
and here is my test method:
@isTest(seealldata=true)
private class test_getTimesheets {
static testmethod void test_getTimesheets_UseCase1() {
TSheetsGetTimesheets tgts = New TSheetsGetTimesheets();
Test.setMock(HttpCalloutMock.class, new RestMock());
Test.startTest();
tgts.getTimesheets();
Test.StopTest();
}
private class RestMock implements HttpCalloutMock {
public HTTPResponse respond(HTTPRequest req) {
String fullJson = 'your Json Response';
HTTPResponse res = new HTTPResponse();
res.setHeader('Content-Type', 'text/json');
res.setBody(fullJson);
res.setStatusCode(200);
return res;
}
}
}
seealldata=true
is often an exercise in futility, and using that annotation is bad practice in all but the tiniest slice of circumstances. Consider removing it and generating your test data.