0

I need to test a behavior for when users have no access to the Document object; not even Read access. I've started w/ a mock user given the standard "Read Only" profile, and I'd like to use the following helper method to remove Read access from the Document object:

public static void removeReadPermission(String myObjectName, PermissionSet myPermissionSet){
    ObjectPermissions myObjectPermissions = new ObjectPermissions();
    myObjectPermissions.PermissionsRead = false;
    myObjectPermissions.PermissionsViewAllRecords = false;
    myObjectPermissions.SObjectType = myObjectName;
    myObjectPermissions.ParentId = myPermissionSet.Id;
    insert myObjectPermissions;
}

However, I get the following error when I run that code:

System.DmlException: Insert failed. First exception on row 0; first error: FIELD_INTEGRITY_EXCEPTION, You must enable at least one permission.: [Permissions]
2

You cannot modify permissions in a test. Instead, you should find a Profile which already exhibits the behavior you desire, and create a User record assigned to it. Then you run as this User.

6
  • I don't believe there are any standard Profiles w/ Document-Read disabled, and tests won't let you use a custom profile. – WEFX Apr 23 '19 at 17:38
  • 2
    That is completely incorrect. You can use custom profiles in a test. What led you to believe you cannot? – Adrian Larson Apr 23 '19 at 17:39
  • All that says is you cannot create a Profile in a test, just like you cannot modify them, as I state in my answer. It does not mean in any way that you cannot create a User and assign them a specific existing Profile which has the attributes you intend to test. – Adrian Larson Apr 23 '19 at 18:01
  • The question linked to here is asking about 1. creating managed packages, and 2. only says that you cannot CREATE a custom profile in tests. It does not say that you cannot USE custom profiles in your tests. – DavidSchach Apr 23 '19 at 18:02
1

I quite dislike tests that rely on too much meta data in the DB. Sure, you have to rely on some of it, such as the schema, but then these are probably more within your control. Profiles, on the other hand, tend to be configured and modified more often by admins, in a more ad-hoc manner at the whim of the business users.

Personally, I think this is another case where an abstraction is required - don't check permissions directly using the Salesforce APIs but instead create an abstraction for checking permissions. You can then have test specific implementation of this abstraction to allow you to exercise the various paths through your logic.

Following the "factory method with dependency injection" pattern we typically employ, use a virtual class with a virtual method for such checks.

The virtual class should include a static method that takes a type (class) and another static method for accessing an instance of that type (that must be derived from the abstract class). The default type is the virtual class's type and this is implemented to use the Salesforce APIs directly.

The production code that needs to check permissions only calls the instance getter and the check method on the returned instance whilst tests provide test implementation(s) of the virtual class that return values appropriate for your testing and critically register it as the class to be instantiated before exercising any of the code.

0

There should be users in your org who do not have access to the Documents object, so use System.RunAs to run the test as one of those users (or create a user with a profile that does not have access).

If there is no profile that does not have access to the Documents object, then there is no reason to write the test. I know that doesn't sound like a best-practice, but it might be an example of going too far to check every possible scenario when a given scenario doesn't exist.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.