TL;DR - Why is my api query not returning child contacts when run via a test?
Problem
Despite being included in the query, the query results from my API method does not include the Contacts column and data when run from the Execute Anonymous function nor my test class, causing my trailhead challenge to fail.
The error message I receive when attempting to complete the challenge is as follows:
Challenge not yet complete in API Study Executing the 'AccountManager' method failed. Either the service isn't configured with the correct urlMapping, is not global, does not have the proper method name or does not return the requested account and all of its contacts.
Description
I am learning about APIs and am currently on the Apex Web Services portion of the Apex Integration Services trailhead. For the hands-on challenge, I've created an apex class and test (listed below). The oddity that I'm encountering is that running the API call within the Developer Console Execute Anonymous function or via the test class does not include the "Contacts" column and data. Stranger still is that this Contacts column is included when I call the API via the Workbench.
Troubleshooting Thus Far
I've tried running the query in my getAccount class manually via the Query Editor in the Developer Console, and it always includes the queried Contacts column. I've also double-checked my getAccount code against a how-to video (link here) and it appears to be identical. I've also played with the URI, using both my sandbox-specific instance and the generic "https://yourInstance.salesforce.com/services/apexrest" code used in the trailhead and in the tutorial video I found.
Code and attempts
Account Manager Apex Class
@RestResource(urlMapping='/Account/*/contacts')
global with sharing class AccountManager {
@HttpGet
global static Account getAccount(){
RestRequest request = RestContext.request;
String accountId = request.requestURI.substringBetween('Account/', '/contacts');
Account result = [SELECT Id, Name, (SELECT Id, Name FROM Contacts) FROM Account WHERE Id=:accountId];
system.debug('result: '+result);
return result;
}
}
Apex Test Class
@isTest
public class AccountManagerTest {
@isTest(SeeAllData=true)
public static void testGetAccount(){
Account a = [SELECT Id FROM Account LIMIT 1];
// Set up a test request
RestRequest request = new RestRequest();
// Set request properties
request.requestUri = 'https://cunning-fox-unspoh-dev-ed.my.salesforce.com/services/apexrest/Account/'+a.Id+'/contacts';
request.httpMethod = 'GET';
// Finally, assign the request to RestContext if used
RestContext.request = request;
Account result = AccountManager.getAccount();
system.assertEquals(a.Id, result.Id);
}
}
Workbench Rest Explorer call
Results from Workbench
{
"attributes": {
"type": "Account",
"url": "/services/data/v51.0/sobjects/Account/0015e000009T7JhAAK"
},
"Id": "0015e000009T7JhAAK",
"Name": "Dickenson plc",
"Contacts": {
"totalSize": 1,
"done": true,
"records": [{
"attributes": {
"type": "Contact",
"url": "/services/data/v51.0/sobjects/Contact/0035e000006WP0LAAW"
},
"AccountId": "0015e000009T7JhAAK",
"Id": "0035e000006WP0LAAW",
"Name": "Andy Young"
}]
}
}
Execute Anonymous Code
RestRequest request = new RestRequest();
request.requestUri =
'https://cunning-fox-unspoh-dev-ed.my.salesforce.com/services/apexrest/Account/0015e000009T7JhAAK/contacts';
request.httpMethod = 'GET';
request.params.put('status', 'Working');
RestContext.request = request;
Account a = AccountManager.getAccount();
system.debug('a: '+a);
Results from both Execute Anonymous and Test Class
Account:{Id=0015e000009T7JhAAK, Name=Dickenson plc}
System.debug()
serializes objects. If you'd puta.Contacts
into that debug, it would show you the contacts. Of course, that's assuming that there are, in fact, Contact records related to your chosen account.