Recipes by Category

App Distribution (2) Bundle logic, interface and services for distribution. App Logic (37) The Apex programming language, workflow and formulas for logic. Collaboration (5) The Salesforce Chatter collaboration platform. Database (29) Data persistence, reporting and analytics. Integration (33) Web Service APIs and toolkits for integration. Security (9) Platform, application and data security. Tools (4) Force.com tooling User Interface (36) Visualforce MVC and metadata-drive user interfaces. Web Sites (12) Public web sites and apps with optional user registration and login.
Beta Feedback
Cookbook Home » Using System.runAs in Test Methods

Using System.runAs in Test Methods

Post by Developer Force  (2010-07-16)

Status: Certified
Level: novice

Problem

Generally, all Apex scripts run in system mode. The permissions and record sharing of the current user are not taken into account; however, you need to verify if a specific user has access to a specific object.

Solution

The system method runAs enables you to write test methods that change user contexts to either an existing user or a new user. All of that user's record sharing is then enforced.

In the following example, a new user is created, based on the standard user profile. In addition, a second user is instantiated, based on the system administrator profile, to demonstrate both ways of generating users for tests. Two accounts are created, and then runAs verifies that the standard user cannot view the administrator account.

@isTest
private class MyTestClass {

   static testMethod void test1(){

      // Retrieve two profiles, for the standard user and the system   
    
      // administrator, then populate a map with them.  
    

      Map<String,ID> profiles = new Map<String,ID>();
      List<Profile> ps = [select id, name from Profile where name = 
         'Standard User' or name = 'System Administrator'];

      for(Profile p : ps){
         profiles.put(p.name, p.id);
      }

      // Create the users to be used in this test.  
    
      // First make a new user.  
    

      User standard = new User(alias = 'standt', 
      email='standarduser@testorg.com', 
      emailencodingkey='UTF-8', 
      lastname='Testing', languagelocalekey='en_US', 
      localesidkey='en_US', 
      profileid = profiles.get('Standard User'), 
      timezonesidkey='America/Los_Angeles', 
      username='standarduser@testorg.com');

      insert standard;

      // Then instantiate a user from an existing profile  
    

      User admin = [SELECT Id FROM user WHERE profileid = 
                    :profiles.get('System Administrator')];

      // Create some test data for testing these two users  
    

      List<Account> accnts = new List<Account>();
      Account a1 = 
         new Account(name='Admin Account', ownerid = admin.id);
      Account a2 = 
         new Account(name='Standard Account', ownerid = standard.id);
      accnts.add(a1);
      accnts.add(a2);
      insert accnts;

      // Confirm that the standard user cannot see the admin account  
    

      system.runas(standard){
         accnts.clear();
         accnts = [select id, name from account where id = :a1.id];
         system.debug(accnts.isEmpty() + ' really'+accnts);
         System.assertEquals(accnts.isEmpty(), true);

      }
      // Confirm that the admin user can see the standard account  
    

      system.runas(admin){
         accnts.clear();
         accnts = [select id, name from account where id = :a2.id];
         System.assertEquals(accnts.isEmpty(), false);
      }
   }
} 

Discussion

Note that this class is defined as isTest. Classes defined with the isTest annotation do not count against your organization limit of 1 MB for all Apex scripts.

You can only use runAs in a test method.

Only the following items use the permissions granted by the user specified with runAs:

  • dynamic Apex
  • methods using with sharing or without sharing
  • shared records

The original permissions are reset after runAs completes.

Share

Recipe Activity - Please Log in to write a comment

What's the solution to that issue then Soren?  Can't really hard code IDs for profiles either.

by Andy_Ognenoff__c  (2011-04-21)

The recipe should not reference standard profile names by name. E.g. from line 13:

 
"List<Profile> ps = [select id, name from Profile where name = 'Standard User' or name = 'System Administrator'];"

If the test is run by a user with the language setting other than English, the standard profile names are translated and will therefore not be found. This will cause the test to fail (probably the issue you're experiencing, Osama Nasir)

We're missing something like a "developer name" for standard profiles.

by soren.krabbe07092010  (2011-04-18)

List<Profile> prf = [Select id from Profile where Name = 'System Administrator'];


this query doesnt execute when a user other than administrator runs it. Why?

by Osama Nasir  (2010-10-10)

X

Vote to Verify a Recipe

Verifying a recipe is a way to give feedback to others and broaden your own understanding of the capabilities on Force.com. When you verify a recipe, please make sure the code runs, and the functionality solves the articulated problem as expected.

Please make sure:
  • All the necessary pieces are mentioned
  • You have tested the recipe in practice
  • Have sent any suggestions for improvements to the author

Please Log in to verify a recipe

You have voted to verify this recipe.