3

I have an Apex test that is querying Task records. Custom fields on Activity are being removed by stripInaccessible.

The test is not using a runAs, so it should be running in system mode and should have access to all fields or am I mistaken?

Why are the custom fields being removed by stripInaccessible? Am I misunderstanding how it works?

2
  • 3
    You misunderstand; tests still run under a user, the one under which you ran the tests. It is just that you would normally be logged in as an admin-like user. Even admins, especially on scratch orgs, need to be given CRUD/FLS permissions for custom objects.
    – Phil W
    Jul 24, 2022 at 7:41
  • @PhilW You could post this answer?
    – arut
    Jul 24, 2022 at 10:04

2 Answers 2

5

Tests still run under a user, the one under which you ran the tests.

It is just that you would normally be logged in as an admin-like user. Even admins, especially on scratch orgs, need to be given CRUD/FLS permissions for custom objects.

In your case, I suggest that you have not granted the CRUD/FLS access to the objects and/or fields involved in the tests.

We deal with this by defining a permission set that grants full access to all our objects and their fields and assigning this to the user used for test execution on the given org.

1
  • makes perfect sense, thank you
    – aaron
    Jul 24, 2022 at 18:03
3

Apex always has access to all fields. System/user mode doesn't change that fact. This means that you can write a method like this:

@AuraEnabled public static String getAccountStatus(Id recordId) {
  return [SELECT Status__c FROM Account WHERE Id = :recordId].Status__c;
}

And, assuming the user has access to the record, the Status__c value will always be returned, even if the user doesn't have access to the field. Whether or not the user will have access is determined by if inherited sharing, with sharing, without sharing, or no sharing model is defined, and whether or not they have access to the record in question. That's why stripInaccessible was created in the first place. To provide a way to restrict access to data the user should not see.

All Salesforce transactions run in the context of a user, every time, without fail. There are some special circumstances where the user might be a phantom user (e.g. during package installs, or for some automated processes), but a user will always be associated with a transaction. Of course, this includes unit tests. When you're running a test, it runs in your user context by default.

You can easily prove this to yourself by writing a simple test:

@isTest static void test() {
  System.assert(false, [SELECT Name FROM User WHERE Id = :UserInfo.getUserId()].Name]);
}

You will always see your name displayed there.

As Phil mentions, a permission set is useful to have to assign to users when running tests. However, this is also a moment to mention that if you're having problems like this in a unit test, that means your user likely isn't set up correctly and you can't actually test these functions "for real" (e.g. using the user interface). The disruptions go beyond just automated Apex testing and could affect your manual tests as well.

I'd recommend that you make sure your user profile (typically System Admin, but it could be something else) has all the object and field level access it needs so you can do proper testing.

1
  • makes perfect sense, thank you
    – aaron
    Jul 24, 2022 at 18:03

You must log in to answer this question.

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