function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Keith654Keith654 

How to test CRUD Security and FLS despite implicit describe caching?

In preparation for the Force.com AppExchange Security Review (see e.g. Requirements Checklist) I have been trying to write unit tests for my application's CRUD security and FLS logic.

 

The two tests below demonstrate the problem that I have got stuck on. System.runAs can have an impact on the describe call result as isUpdateable is false in the first test class and true in the second. But the first obtained describe data remains cached both within a test method and across the whole test class.

 

I'm looking for suggestions on how to write CRUD security and FLS tests given this unexpected behavior.

 

Thanks, Keith

 

@isTest
private class DescribeFalseTest {

    @isTest
    static void testOne() {
    
        // Observed bizarre behavior: if first call is false rest will be false
        System.runAs(readOnlyUser()) {
            System.assertEquals(false, Account.SObjectType.getDescribe().isUpdateable());
        }

        System.assertEquals(false, Account.SObjectType.getDescribe().isUpdateable());
    }

    @isTest
    static void testTwo() {

        System.assertEquals(false, Account.SObjectType.getDescribe().isUpdateable());
        
        System.runAs(readOnlyUser()) {
            System.assertEquals(false, Account.SObjectType.getDescribe().isUpdateable());
        }
    }
    
    private static User readOnlyUser() {

        Profile p = [select Id, Name from Profile where Name = 'Read Only'];
        User u = new User(
            UserName = 'test-user@test-company.com',
            FirstName = 'Test-First-Name',
            LastName = 'Test-Last-Name',
            Alias = 'test',
            Email = 'test-user@test-company.com',
            EmailEncodingKey = 'UTF-8',
            LanguageLocaleKey = 'en_US',
            LocalesIdKey = 'en_US',
            TimezonesIdKey = 'America/Los_Angeles',
            ProfileId = p.Id
            );
        insert u;
        return u;
    }
}

 

@isTest
private class DescribeTrueTest {

    @isTest
    static void testOne() {
    
        // Observed bizarre behavior: if first call is true rest will be true
        System.assertEquals(true, Account.SObjectType.getDescribe().isUpdateable());
        
        System.runAs(readOnlyUser()) {
            System.assertEquals(true, Account.SObjectType.getDescribe().isUpdateable());
        }
    }

    @isTest
    static void testTwo() {

        System.runAs(readOnlyUser()) {
            System.assertEquals(true, Account.SObjectType.getDescribe().isUpdateable());
        }

        System.assertEquals(true, Account.SObjectType.getDescribe().isUpdateable());
    }
    
    private static User readOnlyUser() {

        Profile p = [select Id, Name from Profile where Name = 'Read Only'];
        User u = new User(
            UserName = 'test-user@test-company.com',
            FirstName = 'Test-First-Name',
            LastName = 'Test-Last-Name',
            Alias = 'test',
            Email = 'test-user@test-company.com',
            EmailEncodingKey = 'UTF-8',
            LanguageLocaleKey = 'en_US',
            LocalesIdKey = 'en_US',
            TimezonesIdKey = 'America/Los_Angeles',
            ProfileId = p.Id
            );
        insert u;
        return u;
    }
}
Keith654Keith654

Two follow ons to this:

 

 

ygluckygluck

Hi Keith,

We’d be happy to help you with this and thanks for logging the issues you came across.  We are actively investigating them and working on a solution.  Please email securecloud .at. salesforce.com if you would like to correspond with the team directly in the future.

Brian SobyBrian Soby

Hi Keith,

 

That's indeed a bug.  It's filed and we're working to resolve it.  It seems to cache across different test methods and classes so I don't see an easy workaround.

 

-Brian Soby

 

Keith654Keith654

Brian,

 

Do you now have a plan for when a fix for this should be rolled out?

 

Keith

Brian SobyBrian Soby

Hi Keith,

 

We hope to resolve it as soon as possible but don't have a fixed date available.

 

-Brian Soby

Keith654Keith654

Any update on the rollout?

 

Thanks,

Keith

LiamCoLiamCo

Sorry to resurrect an old post but I have just smacked into the same problem. Is there any solution on the horizon ?

 

thanks,

 

Liam

rungerrunger

Are you sure your situation isn't different.  I'm not seeing this problem anymore.

LiamCoLiamCo

My symptoms are the same. Here is the code I'm using

 

 

    static testMethod void myUnitTest() {
	

		Profile p2 = [select id,name  from profile where name= 'Sales Manager']; 

		integer numberVal = (Math.random() * 100).intValue();
		 
		string testName = 'Standarduser88' + numberVal + '@testorg.com';
	
        User u2 = new User(alias = 'standt', email=testName, 
	            emailencodingkey='UTF-8', lastname='Testing', languagelocalekey='en_US', 
	            localesidkey='en_US', profileid = p2.Id, 
	            timezonesidkey='America/Los_Angeles', username=testName);
	            
	        insert u2;

	
			
			System.runas(u2)
			{

				SObjectType sObjType = Schema.Sobjecttype.Opportunity.getSObjectType(); 
				
            	System.debug('Current User: ' + UserInfo.getUserName());
                System.debug('Current Profile: ' + UserInfo.getProfileId()); 
				
				Map<String, Schema.SObjectField> M = sObjType.getDescribe().fields.getMap();
							
				Schema.DescribeFieldResult F = M.get('FG_Number_of_Insertion__c').getDescribe();
				boolean visible            = f.isAccessible();
				boolean editable          = f.isUpdateable();
				
				system.debug('FIELD IS visible - ' + visible);
				system.debug('FIELD IS editable - ' + editable);
				
				system.assertEquals(false, visible, 'VISIBLE');
				system.assertEquals(false, editable, 'EDITABLE');
				
			}

 

 

I have the same code in a separate class but with a separate profile. Each profile has different access to the field. If I run the classes individually they work fine. If I put both methods in the same class or run the classes together then one of them will fail.

 

I have a case with premier support so I'm hoping for some kind of resolution but I wondered if anyone had found a workaround.

 

Thanks,

 

Liam

rungerrunger

Ah, I see the difference.  You're looking at the fields, and the original poster was just getting the describes on the sobjects.

This is a bug.  Do you have a case ID for your case with support?

 

LiamCoLiamCo

 

It's case # 05320459.

 

Thanks,

 

Liam