2

I am trying to test a sub query using SOQL Lib

In the docs it says will ignore all filters and relations so how is this possible if I cannot create a relationship?

My example is to get all opportunities for an Account who's amount value is between 500 and 2,000

Account Selector

 public AccountSelector getOpportunitiesByAmount(Id account_id){
    with(SOQL.SubQuery.of('Opportunities')
        .with(Opportunity.Id, Opportunity.Amount)
        .whereAre(SOQL.FilterGroup
            .add(SOQL.Filter.with(Opportunity.Amount).greaterThan(500))
            .add(SOQL.Filter.with(Opportunity.Amount).lessThan(2000))
            .conditionLogic('1 AND 2')
        )
    )
    .whereAre(Filter.with(Account.Id).equal(account_id));

    return this;
}

Controller The debug is to make sure that the expected result works which is does

    public static List<Account> getOpportunitiesInAccount(String account_id) {  
    // making sure it works      
    List<Account> accList = AccountSelector.query()
                            .getOpportunitiesByAmount(account_id)
                            .mockId('AccountController.getOpportunitiesInAccount')
                            .toList();
    Opportunity opps = accList[0].Opportunities;
    System.debug(opps.Amount);
     
    return AccountSelector.query()
                            .getOpportunitiesByAmount(account_id)
                            .toList();
}

Test

At the moment I am getting the error - System.QueryException: List has no rows for assignment to SObject

@IsTest
static void opportunityForAccountInRange(){ 

    List<Opportunity> opportunity_list = new List<Opportunity>{
        new Opportunity(AccountId = '0012o00003ORxRcAAL', Amount = 500),
        new Opportunity(AccountId = '0012o00003ORxRcAAL', Amount = 1500),
        new Opportunity(AccountId = '0012o00003ORxRcAAL', Amount = 2000)
    };
    SOQL.setMock('AccountController.getOpportunitiesInAccount', opportunity_list);


    Account account_for_test = new Account(Id = '0012o00003ORxRcAAL', Name = 'Test');
    SOQL.setMock('AccountController.getOpportunitiesInAccount', account_for_test);

    List<Account> result = AccountController.getOpportunitiesInAccount('0012o00003ORxRcAAL');

    // Opportunity opps = result[0].Opportunities;
    // System.debug(opps.Amount);
    
    Assert.areEqual(1, result.size());
    
}

I was hoping that if anyone has experience using SOQL Lib if they could help shed some light around testing sub queries.

1 Answer 1

3

To test sub-queries you should use the deserialization mechanism with JSON data (to write on non-writable fields), as described in the documentation:

Sub-Query

To mock a sub-query we need to use deserialization mechanism. There are two approaches, using JSON string or Serialization/Deserialization. Then after deserialization to desired SObjectType, pass the data to SOQL by calling .setMock method.

Using JSON String

By passing simple String, it is possible to write non-writable fields, like Name on Contact object.

@IsTest
static void getAccountsWithContacts() {
   List<Account> mocks = (List<Account>) JSON.deserialize(
       '[{ "Name": "Account Name", "Contacts": { "totalSize": 1, "done": true, "records": [{ "Name": "Contact Name", "Email": "[email protected]" }] }  }],
       List<Account>.class
   );

   List<Account> accounts;

   Test.startTest();
   SOQL.setMock('AccountsController.getAccountsWithContacts', mocks);
   accounts = AccountsController.getAccountsWithContacts();
   Test.stopTest();

   Assert.isNotNull(accounts);
   Assert.isNotNull(accounts[0].contacts);
   Assert.areEqual(1, accounts[0].contacts.size());
}

I suggest reading the documentation on this because it also explains how to use the JSON.serialize method to build the mocked data with lists and maps instead of a single string.

You must log in to answer this question.

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