28

This is probably a very silly question but I recall on some forums a conversation in regards to this subject. I'm working on my code coverage for an apex class. For that test I need to use the user object to obtain certain information from a number of users. I need to get access to Country, Title, and some other information, can be from any user.

This is not big deal. The question is,

if need I users for my test, should I use real user ids?

or

Can I create users inside the test class?

Why I asking this... I believe, like a mentioned on the first lines of this post, that I need to have free licences in order for me to create those users on the test class. I think that a conversation on this subject took place with Jeff Douglas in a forum, but can't remember the outcome of it. Anyone can explain what is the actual situation on this matter?

2 Answers 2

38

Taken from the documentation:

Generally, all Apex code runs in system mode, where the permissions and record sharing of the current user are not taken into account. The system method runAs enables you to write test methods that change the user context to an existing user or a new user so that the user’s record sharing is enforced. The runAs method doesn’t enforce user permissions or field-level permissions, only record sharing.

You can use runAs only in test methods. The original system context is started again after all runAs test methods complete.

The runAs method ignores user license limits. You can create new users with runAs even if your organization has no additional user licenses.

@isTest
private class TestRunAs {
    public static testMethod void testRunAs() {
        // Setup test data
        // This code runs as the system user
        Profile p = [SELECT Id FROM Profile WHERE Name='Standard User']; 
        User u = new User(Alias = 'standt', Email='[email protected]', 
            EmailEncodingKey='UTF-8', LastName='Testing', LanguageLocaleKey='en_US', 
            LocaleSidKey='en_US', ProfileId = p.Id, 
            TimeZoneSidKey='America/Los_Angeles', UserName='[email protected]');

        System.runAs(u) {
            // The following code runs as user 'u' 
            System.debug('Current User: ' + UserInfo.getUserName());
            System.debug('Current Profile: ' + UserInfo.getProfileId()); 
        }
    }
}
8

Building on this answer, I construct my test classes @TestSetup methods such that I can create an arbitrary number of unique users using a shortened 8-char GUID to init the names and emails, like so:

@IsTest  
public with sharing class NotificationTests {
  @TestSetup  
  private static void setup() {    
    // Setup 4 Test Users
    Profile p = [SELECT Id FROM Profile WHERE Name='Standard User']; 
    List<User> uu = new List<User>();

    while (uu.size() < 5) {
      Blob b = Crypto.GenerateAESKey(128);
      String h = EncodingUtil.ConvertTohex(b);
      String uid = h.SubString(0,8);
      User u = new User(Alias = uid, Email= uid + '@myorg.com', 
          EmailEncodingKey='UTF-8', LastName='Testing', LanguageLocaleKey='en_US', 
          LocaleSidKey='en_US', ProfileId = p.Id, 
          TimeZoneSidKey='America/New_York', UserName= uid + '@myorg.com');      
      uu.add(u);
    }
    insert(uu);
  }

  @IsTest
  public static void myTest() {
    /* ... */
  }
}
6
  • 1
    Hi @Shane. Now I don't insert the users anymore on the test classes, it is bad practice..... that's if you believe on anything that Dan Appleman has to say about Apex :) ... Dec 5, 2018 at 6:05
  • 1
    Hmmm. But what is the alternative if you need a user in your test? Note I think this only makes sense with SeeAllData=false; also I typically develop using DX scratch orgs that have no data at all :).
    – Shanerk
    Dec 5, 2018 at 11:03
  • 2
    I never use SeeAllData=true ... the approach I use is to add , not to insert, a user in your test class. Salesforce creates this temporary space for that User and you can pass his Id or any other field to your test class without doing any DML operation. Dec 5, 2018 at 13:36
  • 1
    That is nice unless you have more than one test method in your class which needs to use the same dataset. Maybe Dan Appleman is too much of a purist ;)
    – Shanerk
    Dec 5, 2018 at 15:08
  • 4
    @CarlosNaranjo What exactly constitutes inserting a user in a test class as a bad practice?
    – Arthlete
    Feb 25, 2020 at 18:02

You must log in to answer this question.

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