0

I have a class where I am using a method that returns the application label of the current logged in user. I am using that class method in another class method and based on the returned app name, I am performing certain logic.

Issue is whenever I am trying to cover it in test class, my test class is failing at the query where I am trying to fetch the appinfo based on current logged in user information. It's saying list has no rows assignment to sobject.

In my test class, current logged in user is fetched correctly and I am running it in current user context, but still at that particular query it's failing. Below is the query:

UserAppInfo using = [select id, AppDefinitionId from UserAppInfo where userid=:userInfo.getUserId()]
1
  • have you tried creating the UserAppInfo record on your test class?
    – McCubo
    Commented Jun 15, 2022 at 9:57

1 Answer 1

0

First principles:

  • UserAppInfo is not considered as metadata available to a testmethod. It is an SObject that must be mocked (like Account or Opportunity)

Now, you might think you could mock UserAppInfo like this:

AppDefinition[] appDefs = [SELECT Id, DeveloperName FROM AppDefinition];
// Given UserAppInfo
UserAppInfo[] mockUserAppInfos = new List<UserAppInfo> {
        new UserAppInfo(UserId = UserInfo.getUserId(), 
                        AppDefinitionId  = appDefs[0].Id,
                        FormFactor ='Large')
        };
insert mockUserAppInfos;

But...this won't work because you will get this error:

System.DmlException: Insert failed. First exception on row 0; first error: MISSING_ARGUMENT, 
                     The AppDefinition ID is not specified.: [AppDefinitionId]

What?!

Turns out that while SOQL Query Editor returns AppDefinition.Id as something like this 06m40000000n7heAAA, the same query executed in APEX returns 06m000000000000000.

So, you'll need to mock UserAppInfo using JSON.deserialize method:

Map<String,Object> fldValByFldName = new Map<String,Object> {
 'AppDefinitionId' => '06m00000000000000',
 'FormFactor' => 'Large',
 'UserId' => UserInfo.getUserId()
};
UserAppInfo[] mockUserAppInfos = new List<UserAppInfo> {
   (UserAppInfo) JSON.deserialize(JSON.serialize(fldValByFldName),UserAppInfo.class
};

Now, if the code-under-test needs to query the mocked UserAppInfo, you'll need to rewrite the code-under-test to use a Selector class to wrap the query for UserAppInfo. This will allow you inject a mockSelector (in a fashion analogous to injecting a mock HttpResponse for callouts) at testmethod time.

You must log in to answer this question.

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