4

I have an apex method that needs to check if a user has create permission on an object in order to successfully complete the method. It works for me.

But Im having an issue writing the test. I do not know how to assign the create permission to the user I use to run the test. I tried the below but its nonsense frankly. I dont know what to do with the permission set. Someone mentioned I might have to create a profile on the machine that will run the test with that permission and then get that?Or can I create the profile in the test? Or do I need to go a whole other route?

PermissionSet ps = [SELECT Id FROM PermissionSet WHERE Name = 'Account_Product__c'];

    PermissionSetAssignment psa = new PermissionSetAssignment();
    psa.AssigneeId = userList[0].Id;
    psa.PermissionSetId = ps.Id;
    insert psa;

    System.runAs(userList[0])
    {
        Account acc = AceTestData.createAccount();
        Product__c [] prodList = new Product__c[]{};
        prodList.add(new Product__c(Name='Test1', Category__c='Item1', Sub_Category__c='Item2'));
        prodList.add(new Product__c(Name='Test2', Category__c='Item3', Sub_Category__c='Item4')); 
        insert prodList;

        Account_Product__c acp = new Account_Product__c(Account__c = acc.Id, Product__c = prodList[0].Id);
        insert acp;
        List<String> listS = new List<String>{};
        listS.add(prodList[0].Id);
        listS.add(prodList[1].Id);

        Account_Product__c[] testResult = DealAccountProductRevenueController.getAccountProducts(acc.Id, listS);
        System.assertEquals(testResult.size(), 2);
        System.assertEquals(testResult[0].Id, acp.Id);
    }
3

I agree in general line with Viasur, but my opinion for PermissionSet records is different - is Salesforce they are considered metadata, not data. Therefore you should test your real PermissionSet as this is a part of configuration of your organization, it is not just a record.

Therefore you should select your real PermissionSet in test. It will be available with (SeeAllData=False), as PermissionSet records are metadata objects.

Problem with your code is line that you are using for NAME is incorrect, you are trying to use predicted API name, but I found that Salesforce does not attaches __c for PermissionSet API names, moreover you can not even save it with __c at the end. So it is guaranteed your API name in SOQL is incorrect. Use Exact line that you see in your UI and do not attach anything to it. Probably it will look like:

PermissionSet ps = [SELECT Id FROM PermissionSet WHERE Name = 'Account_Product'];

Make sure this returns a record. Rest of the test should be fine.

Advantages of this approach:

  • you are testing your real Metadata, if for example someone change real PermissionSet in a way users are no longer able to do their work your test will fail as a signal for broken functionality. Test with created permission set inside it will still pass and you can be unaware of fatal changes.

Downsides of this approach:

  • PermissionSet Name must be same from Sandbox to Production. This downside is nullified if you deploy PermissionSet together with code (yes they are metadata) and do not recreate it manually in Prod.
1

Normally you should create your data for all your tests. Something like a Centralize Object Initialization approach can be very helpful.I can see you are using something like that for you account creation on line

 Account acc = AceTestData.createAccount(); 

, correct?

Do the same with user and permission sets.

So you need to create a Permission set with the configuration you need to run for that permission set. Use Eclipse Schema to see all fields available for your new PermissionSet.

PermissionSet ps = new PermissionSet(); 

Set up your permission set and then build you user/user:

User us = new User(); 

Can't see if the userList is a SOQL or a result of a helper class or something similar. If it is a SOQL I will definaly change it.

There are mandatory fields you need to fill in before getting a new user for your test. Do these on a test factory approach or a Centralize Object Initialization frame work if you can.

So the idea is to built your data for your tests rather than getting data from your system using SOQL queries. After your test data is created and inserted you can use the System.runAs() method.

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.