Skip to main content
2 of 5
added 127 characters in body
cropredy
  • 73.3k
  • 8
  • 128
  • 284

I so much wanted @AdrianLarson answer to be right as it is easy to fabricate but while it works at compile time, at run time, the deserialized AggregateResult is empty ( debug displays as {} ).

So, here's what I did:

Create an AggregateResultProxy object

/**
 * AggregateResult can't be mocked so wrap with AggregateResultProxy
 * which can be mocked by test methods. 
 */

public class AggregateResultProxy {

    Map<String,Object> valuesByAlias = new Map<String,Object> ();

    public AggregateResultProxy withAggregateResult(AggregateResult groupedResult) {
        String groupedResultJson = JSON.serialize(groupedResult);
        this.valuesByAlias = (Map<String,Object>) JSON.deserializeUntyped(groupedResultJson);
        return this;
    }
    public AggregateResultProxy withAliasAndValue(String alias, Object val) {
        this.valuesByAlias.put(alias,val);
        return this;
    }

    public Map<String,Object> getValuesByAlias() {return this.valuesByAlias;}
}

My selector method

return not a List<AggregateResult> but instead a List<AggregateResultProxy>

AggregateResultProxy[] mySelectorMethod(...) {
   AggregateResultProxy[] groupedResultProxies = new List<AggregateResultProxy)();
   for (AggregateResult groupedResult: 
         [SELECT COUNT(ID) RECORDCOUNT, Status STATUS
            FROM Asset 
            WHERE ...
            GROUP BY Status ] ) {
    groupedResultProxies.add(
      new AggregateResultProxy().withAggregateResult(groupedResult));
  }
  return groupedResultProxies;
}

My runtime code

public void doStuff() {
  for (AggregateResultProxy groupedResultProxies :AssetsSelector.newInstance().mySelectorMethod() ) {
    Map<String,Object> groupedResultProxy = groupedResultProxies.getValuesByAlias();
    System.debug('Status=' + groupedResultProxy.get('STATUS'));
    System.debug('Count=' + groupedResultProxy.get('RECORDCOUNT')); 
  }
}

which might display

Status= Active
Count= 23
Status=Canceled
Count=6 

and my testmethod

using ApexMocks (you could of course use your own favorite dependency injection approach)

fflib_ApexMocks mocks = new fflib_ApexMocks();
// given mocked AggregateResults
AggregateResultProxy[] mockedGroupedResults = new List<AggregateResultProxy> {
   new AggregateResultProxy()
     .withAliasAndValue('STATUS','Active')
     .withAliasAndValue('RECORDCOUNT', 2),
   new AggregateResultProxy()
     .withAliasAndValue('STATUS','Cancelled')
     .withAliasAndValue('RECORDCOUNT', 7)
}; 
// Given mock selector (stubbed return val)
AssetsSelector mocksSelector = (AssetsSelector) mocks.mock(AssetsSelector.class);
mocks.startStubbing();
mocks.when(mocksSelector.sObjectType()).thenReturn(Asset.SObjectType);
mocks.when(mocksSelector.mySelector(...))
                .thenReturn(mockedGroupedResults);
mocks.stopStubbing();
// Given mocks injected
Application.Selector.setMock(mocksSelector);

// When myMethodUnderTestIsCalled
myObject.doStuff();
// Then verify ...
...asserts or apexMocks verifies go here
cropredy
  • 73.3k
  • 8
  • 128
  • 284