1

Let's say there's a Custom Permission OrderBulkCancel that grants the running user the ability to cancel more than one order in a transaction. The Custom Permission is evaluated at runtime with:

if (FeatureManagement.checkPermission('OrderBulkCancel')) {..}

When the testmethod runs, if the running user has the permission, the test passes; if the running user does not have the permission, the test fails. That is, org settings influence the test execution.

But of course, it is bad practice to rely on org settings for testmethods, you should mock the permission and assign to the running user.

What is the easiest way to do this?

1 Answer 1

7

As many other answers have stated such as this one, custom permissions are mocked by

  • first mocking a Permission Set,
  • then assigning the custom permission (as a SetupEntityAccess) to that permission set
  • then assigning the permission set to the user

But the key is that this permission set assignment to the running user has no effect unless your code under test is executed within a System.runAs(..) {}. If the running user had the permission set assigned as part of org data it would apply, but if assigned to the very same user in the testmethod, it does not apply unless a System.runAs() scopes the execution of the code under test.

This is an easy trap to fall into as a lot of testmethods are written without mocking a user and/or using System.runAs. It is easy to get sloppy and assume you can assign permission sets to the default running user (you) and assume they'll stick just like mocking other sobject data.

Does not work

insert new PermissionSetAssignment(AssigneeId=UserInfo.getUserId(),
                                   PermissionSetId=mockedPermissionSetId);
Test.startTest();
myCodeUnderTest.doStuff();
Test.stopTest();
// assertions - fail because FeatureManagement.checkPermission returns false

Works

insert new PermissionSetAssignment(AssigneeId=UserInfo.getUserId(),
                                   PermissionSetId=mockedPermissionSetId);
Test.startTest();
System.runAs(new User(Id = UserInfo.getUserId()) {
  myCodeUnderTest.doStuff();
}
Test.stopTest();
// assertions pass because FeatureManagement.checkPermission returns true
2
  • 1
    One more important thing - Before inserting the permissionsetassignment, You must first run a query to see if the permission set is already assigned to the running user - SELECT Id FROM PermissionSetAssignment WHERE AssigneeId = :UserInfo.getUserId() AND PermissionSetId = :ps.Id]. Commented Aug 10, 2021 at 16:16
  • 1
    @AdityaNaag yes and no -- if you mock the permissionSet, by definition it will not already be assigned
    – cropredy
    Commented Aug 10, 2021 at 16:18

You must log in to answer this question.

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