+ Start a Discussion
John Lay 9John Lay 9 

Unable to validate AccountManager APEX Web Service Trailhead Challenge

I've completed the challenge, it has 100% coverage. I've checked all the method names. The URL is valid. I've used Work Bench and curl to test and even tested with multiple Accounts with and without contacts.

I know on other challenges, punctionation was important.  What about the defination of the return? Are there expected names?

I built a class to hold Account ID & Name along with a List of Contact names and IDs. Is this my issue?  Anyone else have a challenge with this challenge?


Any help or hints will be appreciated.

Here are snippets of my code:

@RestResource(urlMapping='/Accounts/*/contacts')
global with sharing class AccountManager {

....

global class APIAccount {
        public ID Id;
        public String Name;
        List<APIContact> Contacts;

...

@HttpGet
    global static APIAccount getAccount() {
        RestRequest request = RestContext.request;
...
 
Best Answer chosen by John Lay 9
Lei ShiLei Shi
You don't have to create a separate Class or a Map. 

Below please find my working code, and be careful with the lower case for contacts.
 
@RestResource(urlMapping='/Accounts/*/contacts')
global class AccountManager {
    @HttpGet
    global static Account getAccount() {
        RestRequest req = RestContext.request;
        String accId = req.requestURI.substringBetween('Accounts/', '/contacts');
        Account acc = [SELECT Id, Name, (SELECT Id, Name FROM Contacts) 
                       FROM Account WHERE Id = :accId];
		return acc;
    }
}

 

All Answers

SinanBunniSinanBunni
Hello,

I have a similar problem - Salesforce failed to validate my solution, as below:
 
@RestResource(urlMapping='/Account/*/contacts')
global class AccountManager {
	
	@HttpGet
	global static Map<String, String> getAccount() {
		RestRequest request = RestContext.request;
		System.debug(request);
		String accountId = request.requestURI.substringBetween('Account/', '/contacts');
		System.debug('AccountManager - accountId: ' + accountId);
		
		Map<String, String> IdToName = new Map<String, String>();
		Account account =  [SELECT Id, Name FROM Account WHERE Id = :accountId];
		List<Contact> contacts = [SELECT Id, Name FROM Contact WHERE AccountId = :account.Id];
		
		IdToName.put(account.Id, account.Name);
		
		for (Contact con : contacts) {
			IdToName.put(con.Id, con.Name);
		}
		
		return IdToName;
	} // end getAccount method 
}

any help is truely appreciated. Thanks you, Sinan
Lei ShiLei Shi
You don't have to create a separate Class or a Map. 

Below please find my working code, and be careful with the lower case for contacts.
 
@RestResource(urlMapping='/Accounts/*/contacts')
global class AccountManager {
    @HttpGet
    global static Account getAccount() {
        RestRequest req = RestContext.request;
        String accId = req.requestURI.substringBetween('Accounts/', '/contacts');
        Account acc = [SELECT Id, Name, (SELECT Id, Name FROM Contacts) 
                       FROM Account WHERE Id = :accId];
		return acc;
    }
}

 
This was selected as the best answer
SinanBunniSinanBunni
Thank you Lei Shi - initially was going with your approach but then the challenge specifically asked us to return Id and Name of Account and Contacts therefore was going with a Map collection.

Thanks for your insight,

Sinan
Esteve GraellsEsteve Graells
For the trailheaders with problemas getting validation on this exercise:
  • The result must be an account (its how I passed) as Lei Shi pointed it out
  • Be very very careful with no records returned from your query as could a nightmare as I faced. Solved by adding: @isTest(SeeAllData=true)
I think it is very woth, at least it was for me to read this article about this: Demystifying SeeAllData in Unit Tests http://opfocus.com/blog/demystifying-seealldata-in-unit-tests/.

All the best,
Esteve
 
Naveen ChoudharyNaveen Choudhary

AccountManager Apex Class


@RestResource(urlMapping='/Accounts/*/contacts')
global class AccountManager {
    @HttpGet
    global static Account getAccount() {
        RestRequest req = RestContext.request;
        String accId = req.requestURI.substringBetween('Accounts/', '/contacts');
        Account acc = [SELECT Id, Name, (SELECT Id, Name FROM Contacts) 
                       FROM Account WHERE Id = :accId];
        return acc;
    }
}


TEST CLASS

@isTest
private class AccountManagerTest {

    private static testMethod void getAccountTest1() {
        Id recordId = createTestRecord();
        // Set up a test request
        RestRequest request = new RestRequest();
        request.requestUri = 'https://na1.salesforce.com/services/apexrest/Accounts/'+ recordId +'/contacts' ;
        request.httpMethod = 'GET';
        RestContext.request = request;
        // Call the method to test
        Account thisAccount = AccountManager.getAccount();
        // Verify results
        System.assert(thisAccount != null);
        System.assertEquals('Test record', thisAccount.Name);

    }

    // Helper method
        static Id createTestRecord() {
        // Create test record
        Account TestAcc = new Account(
          Name='Test record');
        insert TestAcc;
        Contact TestCon= new Contact(
        LastName='Test', 
        AccountId = TestAcc.id);
        return TestAcc.Id;
    }      
}

After saving it "Run All" test from developer console. It'll help you to clear the challange.

Please choose it as best answer.
Mustafa GuldoganMustafa Guldogan
I spent ~ an hour to solve this mystery.
I looked at the developer console log after ruinning the challange and found '/contacts' (lower case) was passed by the engine.
replacing '/Contacts' --> '/contacts' in my code solved my problem.
I may help somebody.
 
George WilliamsGeorge Williams
Esteve,

Wouldn't it be more appropriate to use a @TestSetup method insead of SeeAllData=True to follow SF unit testing standards?
Kellan ScheiberKellan Scheiber
Unreal, Mustafa THANK YOU!

That was my issue has well, I could not get the List to populate with data and once I updated to Contacts from contacts my List populated and I passed the challenge.

 
Janakiraman ChandravadhanJanakiraman Chandravadhan
Thankyou Naveen, it helped!
tbaila tbailatbaila tbaila
Thanks Naveen !
Jayanth B 2Jayanth B 2
Optimized code, refer in case required.

@RestResource(urlMapping='/Accounts/*/contacts')
global class AccountManager {
 @HttpGet
    global static Account getAccount(){
       RestRequest request =  RestContext.request;
        return [Select id, name,(SELECT id,name from Contacts) from Account where id=:request.requestURI.substringBetween('Accounts/',                                  '/contacts')];
}
}


Test class

@isTest
public class AccountManagerTest {

    @isTest public static void executeGetAccount(){
        //making Data ready for Testing
        Account acc = new Account(Name='Jayanth B');
        insert acc;
        insert new Contact(LastName='Jayanth',FirstName='b',AccountId=acc.id);
        
        // Set up a test request
        RestRequest request = new RestRequest();
        request.requestURI = 'https://ap4.salesforce.com/services/apexrest/Accounts/'+(String)acc.id+'/contacts';
        request.httpMethod ='GET';
        //set up request Context 
        RestContext.request =  request;
        // call the method
        Account returnedAcc = AccountManager.getAccount();

    }
}
Charles ThompsonCharles Thompson
@jayanth B 2
Thanks for posting "optimised" code.  Next time, could you mark your code as a code block (in the WYSIWYG editor)?  That makes it easier for future generations to read.

For all who come in the future, the challenge requires the class to start with 
@RestResource(urlMapping='/Accounts/*/contacts')
Note the trailing "/contacts".  The challenge also requires you to specify /contacts on the end of your REST URI.

The class actually doesn't require this, but this unit doesn't make it clear.  You *can* use the urlMapping without '/contacts' and the resulting data is almost identical.  Unfortunately, the challenge doesn't mention this, nor does it test for this simpler (i.e. more easily maintained) usage.  In fact, the challenge should make it clear exactly what type the return result should be and what the URI construction should be.
 
EM3R50NEM3R50N
For anyone else who tries everything here but still gets this message ... 
Methods defined as TestMethod do not support Web service callouts
My problem was that I had a couple test triggers on my Account and Contact objects and for some reason those were causing my Test for this lesson to fail. Soon as I deactivated those triggers the Test passed. 
Sambhav Jain 19Sambhav Jain 19
For anyone who might get stuck:
Its not very clear in instructions, that you have to make a test record for account in your test as Test methods cannot read your Organization data.
So either you create some test resords in test class or enable see all data (@IsTest(SeeAllData=true)).  This will allow to read org data in your test method.
DivyanshD SinghDivyanshD Singh
Apex class

@RestResource(urlMapping='/Accounts/*/contacts')
 @isTest(SeeAllData=true)
global class AccountManager{
	@HttpGet
    global static Account getAccount(){
        RestRequest request=RestContext.request;
        String Accountid=request.requestURI.substringBetween('Accounts/*/contacts');
        Account result=[Select id,name,(Select id,name from contacts) from Account where id =:Accountid];
        return result;
    }
}

Test Class

@isTest
public class AccountManagerTest {
    @isTest static void testgetAccount(){
   //     ID recordId=createTestRecord();
        Account ant=new Account(Name = 'Integration Superbadge Challenge');
        insert ant;
        Contact con=new Contact(LastName='challenging Superbadge' ,Accountid=ant.id);
        insert con;
        RestRequest request=new RestRequest();
        request.requestURI='https://ap5.salesforce.com/services/apexrest/Accounts/' + ant.id + '/contacts';
        request.httpMethod='GET';
        restContext.request=request;
        Account acc=AccountManager.getAccount();
        System.assert(acc != null);
}
}

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.TypeException: Cannot call test methods in non-test context
Mark Z DeanMark Z Dean
For me it was @Charles Thompson's suggestion that worked. I was missing the 's' in contacts. Thanks Charles!
Charles ThompsonCharles Thompson
Glad I could help, Mark :-)
Best of luck with the rest of the trail.
hemanth pendyalahemanth pendyala
Use below line.
String Accountid = request.requestURI.substringBetween('Accounts/','/contacts');