How to test CRUD and FLS in unit tests?Owner is null after insert - Test classComparison fails when converting Opportunity from/to JSONCRUD and FLS enforcementUnit Test is Providing 0% Coverage for Apex TriggerCompilation error with a unit test“Required fields are missing: [ProfileId]: [ProfileId]” when running Apex Class Test for ChatterAnswersAuthProviderRegTestschema.getglobaldescribe needs test classCode Coverage to Test Custom Object Public ListSample test for testing FLS/CRUDHow to cover global class and method in test class

Speeding up thousands of string parses

Advice for making/keeping shredded chicken moist?

Why do Klingons use cloaking devices?

PhD: When to quit and move on?

What is this arch-and-tower near a road?

How to respond to someone who condemns behavior similar to what they exhibit?

Chess problem: Make a crossword in 3 moves

Recursive conversion from ExpandoObject to Dictionary<string, object>

How serious is plagiarism in a master’s thesis?

What is the fundamental difference between catching whales and hunting other animals?

Do intermediate subdomains need to exist?

How frequently do Russian people still refer to others by their patronymic (отчество)?

Has chattel slavery ever been used as a criminal punishment in the USA since the passage of the Thirteenth Amendment?

Contributing to a candidate as a Foreign National US Resident?

Using Sed to add counter to keyword

How to deal with a Murder Hobo Paladin?

Should I hide my travel history to the UK when I apply for an Australian visa?

Do the 26 richest billionaires own as much wealth as the poorest 3.8 billion people?

Who pays for increased security measures on flights to the US?

Show that there are infinitely more problems than we will ever be able to compute

List comprehensions in Mathematica?

What are the differences of checking a self-signed certificate vs ignore it?

What is the addition in the re-released version of Avengers: Endgame?

What does it mean for a bass player to play "on the one"?



How to test CRUD and FLS in unit tests?


Owner is null after insert - Test classComparison fails when converting Opportunity from/to JSONCRUD and FLS enforcementUnit Test is Providing 0% Coverage for Apex TriggerCompilation error with a unit test“Required fields are missing: [ProfileId]: [ProfileId]” when running Apex Class Test for ChatterAnswersAuthProviderRegTestschema.getglobaldescribe needs test classCode Coverage to Test Custom Object Public ListSample test for testing FLS/CRUDHow to cover global class and method in test class






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








3















BACKGROUND



I am working on a managed package and it contains a custom object (X__c) with one custom field (X__c.Fld__c). In the controller I check if a user has Read access to both the object and field:



MyController.cls



public class MyController

public MyController()

public List<X__c> selectX()

if (X__c.SObjectType.getDescribe().isAccessible())
if (X__c.Fld__c.getDescribe().isAccessible())

return [SELECT Id, Fld__c FROM X__c];



return null;




And the test class.



MyControllerTest.cls



public class MyControllerTest

@isTest
static void verifySelectX()

// Given
X__c[] xRecords =
(List<X__c>) TestFactory.create(new X__c(), 2);

// When
xRecords = new MyController().selectX();

// Then
System.assertNotEquals(null, xRecords);
System.assertEquals(2, xRecords.size());


@isTest
static void verifySelectXNoAccess()

// Given
X__c[] xRecords =
(List<X__c>) TestFactory.create(new X__c(), 2);

// Create a user which will not have access to the test object type
User testUser = createUser('Chatter External');
if (testUser == null)
// Abort the test if unable to create a user with low enough acess
return;


// When
System.runAs(testUser)

xRecords = new MyController().selectX();

// Then
System.assertEquals(null, xRecords);





QUESTION



When I deploy the project metadata to our packaging org, it fails because the verifySelectX() test doesn't pass. It's due to the user (admin) who runs the test on deployment does not have access to the object and its fields yet. So can I make sure that the tests pass? I thought this is a common problem, but I couldn't find any info on it.










share|improve this question




























    3















    BACKGROUND



    I am working on a managed package and it contains a custom object (X__c) with one custom field (X__c.Fld__c). In the controller I check if a user has Read access to both the object and field:



    MyController.cls



    public class MyController

    public MyController()

    public List<X__c> selectX()

    if (X__c.SObjectType.getDescribe().isAccessible())
    if (X__c.Fld__c.getDescribe().isAccessible())

    return [SELECT Id, Fld__c FROM X__c];



    return null;




    And the test class.



    MyControllerTest.cls



    public class MyControllerTest

    @isTest
    static void verifySelectX()

    // Given
    X__c[] xRecords =
    (List<X__c>) TestFactory.create(new X__c(), 2);

    // When
    xRecords = new MyController().selectX();

    // Then
    System.assertNotEquals(null, xRecords);
    System.assertEquals(2, xRecords.size());


    @isTest
    static void verifySelectXNoAccess()

    // Given
    X__c[] xRecords =
    (List<X__c>) TestFactory.create(new X__c(), 2);

    // Create a user which will not have access to the test object type
    User testUser = createUser('Chatter External');
    if (testUser == null)
    // Abort the test if unable to create a user with low enough acess
    return;


    // When
    System.runAs(testUser)

    xRecords = new MyController().selectX();

    // Then
    System.assertEquals(null, xRecords);





    QUESTION



    When I deploy the project metadata to our packaging org, it fails because the verifySelectX() test doesn't pass. It's due to the user (admin) who runs the test on deployment does not have access to the object and its fields yet. So can I make sure that the tests pass? I thought this is a common problem, but I couldn't find any info on it.










    share|improve this question
























      3












      3








      3








      BACKGROUND



      I am working on a managed package and it contains a custom object (X__c) with one custom field (X__c.Fld__c). In the controller I check if a user has Read access to both the object and field:



      MyController.cls



      public class MyController

      public MyController()

      public List<X__c> selectX()

      if (X__c.SObjectType.getDescribe().isAccessible())
      if (X__c.Fld__c.getDescribe().isAccessible())

      return [SELECT Id, Fld__c FROM X__c];



      return null;




      And the test class.



      MyControllerTest.cls



      public class MyControllerTest

      @isTest
      static void verifySelectX()

      // Given
      X__c[] xRecords =
      (List<X__c>) TestFactory.create(new X__c(), 2);

      // When
      xRecords = new MyController().selectX();

      // Then
      System.assertNotEquals(null, xRecords);
      System.assertEquals(2, xRecords.size());


      @isTest
      static void verifySelectXNoAccess()

      // Given
      X__c[] xRecords =
      (List<X__c>) TestFactory.create(new X__c(), 2);

      // Create a user which will not have access to the test object type
      User testUser = createUser('Chatter External');
      if (testUser == null)
      // Abort the test if unable to create a user with low enough acess
      return;


      // When
      System.runAs(testUser)

      xRecords = new MyController().selectX();

      // Then
      System.assertEquals(null, xRecords);





      QUESTION



      When I deploy the project metadata to our packaging org, it fails because the verifySelectX() test doesn't pass. It's due to the user (admin) who runs the test on deployment does not have access to the object and its fields yet. So can I make sure that the tests pass? I thought this is a common problem, but I couldn't find any info on it.










      share|improve this question














      BACKGROUND



      I am working on a managed package and it contains a custom object (X__c) with one custom field (X__c.Fld__c). In the controller I check if a user has Read access to both the object and field:



      MyController.cls



      public class MyController

      public MyController()

      public List<X__c> selectX()

      if (X__c.SObjectType.getDescribe().isAccessible())
      if (X__c.Fld__c.getDescribe().isAccessible())

      return [SELECT Id, Fld__c FROM X__c];



      return null;




      And the test class.



      MyControllerTest.cls



      public class MyControllerTest

      @isTest
      static void verifySelectX()

      // Given
      X__c[] xRecords =
      (List<X__c>) TestFactory.create(new X__c(), 2);

      // When
      xRecords = new MyController().selectX();

      // Then
      System.assertNotEquals(null, xRecords);
      System.assertEquals(2, xRecords.size());


      @isTest
      static void verifySelectXNoAccess()

      // Given
      X__c[] xRecords =
      (List<X__c>) TestFactory.create(new X__c(), 2);

      // Create a user which will not have access to the test object type
      User testUser = createUser('Chatter External');
      if (testUser == null)
      // Abort the test if unable to create a user with low enough acess
      return;


      // When
      System.runAs(testUser)

      xRecords = new MyController().selectX();

      // Then
      System.assertEquals(null, xRecords);





      QUESTION



      When I deploy the project metadata to our packaging org, it fails because the verifySelectX() test doesn't pass. It's due to the user (admin) who runs the test on deployment does not have access to the object and its fields yet. So can I make sure that the tests pass? I thought this is a common problem, but I couldn't find any info on it.







      apex unit-test isv fls crud






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Jun 25 at 15:04









      EduardEduard

      2,1452 gold badges8 silver badges29 bronze badges




      2,1452 gold badges8 silver badges29 bronze badges




















          2 Answers
          2






          active

          oldest

          votes


















          5














          There are a few different ways to attack this problem, but the most common is to create a user with permissions, and then use System.runAs to execute your tests.



          I normally grant permissions to my packages via permset and not profiles, so I create a user, give it a permission set that I created, and then run the tests. That way I don't depend on the admin user (or any installed org's profiles) for my tests to be successful and I only depend on things that are included in my package.



          For example:



          @IsTest
          static void myTestPermSet()
          User myUser = new User(<UserPropertiesGoHere>);
          insert u;

          PermissionSetAssignment psa = new PermissionSetAssignment (PermissionSetId = myPermissionSetId, AssigneeId = u.id);

          insert psa;

          System.RunAs(u)
          Test.startTest();

          <test your code here>

          Test.stopTest();

          <asserts go here>







          share|improve this answer






























            3














            The approach we took was to provide a special class, e.g. SecurityUtils, with a bunch of static methods on it that take the DescribeSObjectResult(s) or DescribeFieldResult(s) to be checked, e.g.:



            // Returns true if the user has access to all the specified fields
            public static Boolean canAccessFields(DescribeFieldResult[] fields)


            or



            // Throws an exception if the user doesn't have access to all the specified fields
            public static void mustAccessFields(DescribeFieldResult[] fields)


            With variants for access, create, update and delete against one or several objects and one or several fields. Internally these methods check to see if a test is running and if it is simply passes (return true or exit without exception), otherwise it uses the Salesforce API to apply the real CRUD/FLS tests and responds accordingly. NB: We have a way to force the code to apply real CRUD/FLS for the small number of tests we do want CRUD/FLS to be applied in - the tests for this class itself.



            This approach has some down-sides, the most notable being that the Checkmarx scanner can't see that we do the CRUD/FLS checks, so we have to basically mark every single DML operation and SOQL/SOSL query as being a False Positive and explain that checks were done via our util class in order to pass the security review for our managed package. (BTW, Salesforce has some goodies coming out Winter '20 [with luck] that will make Apex handling of CRUD/FLS much cleaner and easier to implement. However, you'll still want to be able to mock out those new features in unit tests.)



            The up-side: unit tests behave as if the user has access to everything and every operation.






            share|improve this answer

























              Your Answer








              StackExchange.ready(function()
              var channelOptions =
              tags: "".split(" "),
              id: "459"
              ;
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function()
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled)
              StackExchange.using("snippets", function()
              createEditor();
              );

              else
              createEditor();

              );

              function createEditor()
              StackExchange.prepareEditor(
              heartbeatType: 'answer',
              autoActivateHeartbeat: false,
              convertImagesToLinks: false,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: null,
              bindNavPrevention: true,
              postfix: "",
              imageUploader:
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              ,
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              );



              );













              draft saved

              draft discarded


















              StackExchange.ready(
              function ()
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsalesforce.stackexchange.com%2fquestions%2f267194%2fhow-to-test-crud-and-fls-in-unit-tests%23new-answer', 'question_page');

              );

              Post as a guest















              Required, but never shown

























              2 Answers
              2






              active

              oldest

              votes








              2 Answers
              2






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes









              5














              There are a few different ways to attack this problem, but the most common is to create a user with permissions, and then use System.runAs to execute your tests.



              I normally grant permissions to my packages via permset and not profiles, so I create a user, give it a permission set that I created, and then run the tests. That way I don't depend on the admin user (or any installed org's profiles) for my tests to be successful and I only depend on things that are included in my package.



              For example:



              @IsTest
              static void myTestPermSet()
              User myUser = new User(<UserPropertiesGoHere>);
              insert u;

              PermissionSetAssignment psa = new PermissionSetAssignment (PermissionSetId = myPermissionSetId, AssigneeId = u.id);

              insert psa;

              System.RunAs(u)
              Test.startTest();

              <test your code here>

              Test.stopTest();

              <asserts go here>







              share|improve this answer



























                5














                There are a few different ways to attack this problem, but the most common is to create a user with permissions, and then use System.runAs to execute your tests.



                I normally grant permissions to my packages via permset and not profiles, so I create a user, give it a permission set that I created, and then run the tests. That way I don't depend on the admin user (or any installed org's profiles) for my tests to be successful and I only depend on things that are included in my package.



                For example:



                @IsTest
                static void myTestPermSet()
                User myUser = new User(<UserPropertiesGoHere>);
                insert u;

                PermissionSetAssignment psa = new PermissionSetAssignment (PermissionSetId = myPermissionSetId, AssigneeId = u.id);

                insert psa;

                System.RunAs(u)
                Test.startTest();

                <test your code here>

                Test.stopTest();

                <asserts go here>







                share|improve this answer

























                  5












                  5








                  5







                  There are a few different ways to attack this problem, but the most common is to create a user with permissions, and then use System.runAs to execute your tests.



                  I normally grant permissions to my packages via permset and not profiles, so I create a user, give it a permission set that I created, and then run the tests. That way I don't depend on the admin user (or any installed org's profiles) for my tests to be successful and I only depend on things that are included in my package.



                  For example:



                  @IsTest
                  static void myTestPermSet()
                  User myUser = new User(<UserPropertiesGoHere>);
                  insert u;

                  PermissionSetAssignment psa = new PermissionSetAssignment (PermissionSetId = myPermissionSetId, AssigneeId = u.id);

                  insert psa;

                  System.RunAs(u)
                  Test.startTest();

                  <test your code here>

                  Test.stopTest();

                  <asserts go here>







                  share|improve this answer













                  There are a few different ways to attack this problem, but the most common is to create a user with permissions, and then use System.runAs to execute your tests.



                  I normally grant permissions to my packages via permset and not profiles, so I create a user, give it a permission set that I created, and then run the tests. That way I don't depend on the admin user (or any installed org's profiles) for my tests to be successful and I only depend on things that are included in my package.



                  For example:



                  @IsTest
                  static void myTestPermSet()
                  User myUser = new User(<UserPropertiesGoHere>);
                  insert u;

                  PermissionSetAssignment psa = new PermissionSetAssignment (PermissionSetId = myPermissionSetId, AssigneeId = u.id);

                  insert psa;

                  System.RunAs(u)
                  Test.startTest();

                  <test your code here>

                  Test.stopTest();

                  <asserts go here>








                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Jun 25 at 15:14









                  Sebastian KesselSebastian Kessel

                  9,6916 gold badges22 silver badges39 bronze badges




                  9,6916 gold badges22 silver badges39 bronze badges























                      3














                      The approach we took was to provide a special class, e.g. SecurityUtils, with a bunch of static methods on it that take the DescribeSObjectResult(s) or DescribeFieldResult(s) to be checked, e.g.:



                      // Returns true if the user has access to all the specified fields
                      public static Boolean canAccessFields(DescribeFieldResult[] fields)


                      or



                      // Throws an exception if the user doesn't have access to all the specified fields
                      public static void mustAccessFields(DescribeFieldResult[] fields)


                      With variants for access, create, update and delete against one or several objects and one or several fields. Internally these methods check to see if a test is running and if it is simply passes (return true or exit without exception), otherwise it uses the Salesforce API to apply the real CRUD/FLS tests and responds accordingly. NB: We have a way to force the code to apply real CRUD/FLS for the small number of tests we do want CRUD/FLS to be applied in - the tests for this class itself.



                      This approach has some down-sides, the most notable being that the Checkmarx scanner can't see that we do the CRUD/FLS checks, so we have to basically mark every single DML operation and SOQL/SOSL query as being a False Positive and explain that checks were done via our util class in order to pass the security review for our managed package. (BTW, Salesforce has some goodies coming out Winter '20 [with luck] that will make Apex handling of CRUD/FLS much cleaner and easier to implement. However, you'll still want to be able to mock out those new features in unit tests.)



                      The up-side: unit tests behave as if the user has access to everything and every operation.






                      share|improve this answer



























                        3














                        The approach we took was to provide a special class, e.g. SecurityUtils, with a bunch of static methods on it that take the DescribeSObjectResult(s) or DescribeFieldResult(s) to be checked, e.g.:



                        // Returns true if the user has access to all the specified fields
                        public static Boolean canAccessFields(DescribeFieldResult[] fields)


                        or



                        // Throws an exception if the user doesn't have access to all the specified fields
                        public static void mustAccessFields(DescribeFieldResult[] fields)


                        With variants for access, create, update and delete against one or several objects and one or several fields. Internally these methods check to see if a test is running and if it is simply passes (return true or exit without exception), otherwise it uses the Salesforce API to apply the real CRUD/FLS tests and responds accordingly. NB: We have a way to force the code to apply real CRUD/FLS for the small number of tests we do want CRUD/FLS to be applied in - the tests for this class itself.



                        This approach has some down-sides, the most notable being that the Checkmarx scanner can't see that we do the CRUD/FLS checks, so we have to basically mark every single DML operation and SOQL/SOSL query as being a False Positive and explain that checks were done via our util class in order to pass the security review for our managed package. (BTW, Salesforce has some goodies coming out Winter '20 [with luck] that will make Apex handling of CRUD/FLS much cleaner and easier to implement. However, you'll still want to be able to mock out those new features in unit tests.)



                        The up-side: unit tests behave as if the user has access to everything and every operation.






                        share|improve this answer

























                          3












                          3








                          3







                          The approach we took was to provide a special class, e.g. SecurityUtils, with a bunch of static methods on it that take the DescribeSObjectResult(s) or DescribeFieldResult(s) to be checked, e.g.:



                          // Returns true if the user has access to all the specified fields
                          public static Boolean canAccessFields(DescribeFieldResult[] fields)


                          or



                          // Throws an exception if the user doesn't have access to all the specified fields
                          public static void mustAccessFields(DescribeFieldResult[] fields)


                          With variants for access, create, update and delete against one or several objects and one or several fields. Internally these methods check to see if a test is running and if it is simply passes (return true or exit without exception), otherwise it uses the Salesforce API to apply the real CRUD/FLS tests and responds accordingly. NB: We have a way to force the code to apply real CRUD/FLS for the small number of tests we do want CRUD/FLS to be applied in - the tests for this class itself.



                          This approach has some down-sides, the most notable being that the Checkmarx scanner can't see that we do the CRUD/FLS checks, so we have to basically mark every single DML operation and SOQL/SOSL query as being a False Positive and explain that checks were done via our util class in order to pass the security review for our managed package. (BTW, Salesforce has some goodies coming out Winter '20 [with luck] that will make Apex handling of CRUD/FLS much cleaner and easier to implement. However, you'll still want to be able to mock out those new features in unit tests.)



                          The up-side: unit tests behave as if the user has access to everything and every operation.






                          share|improve this answer













                          The approach we took was to provide a special class, e.g. SecurityUtils, with a bunch of static methods on it that take the DescribeSObjectResult(s) or DescribeFieldResult(s) to be checked, e.g.:



                          // Returns true if the user has access to all the specified fields
                          public static Boolean canAccessFields(DescribeFieldResult[] fields)


                          or



                          // Throws an exception if the user doesn't have access to all the specified fields
                          public static void mustAccessFields(DescribeFieldResult[] fields)


                          With variants for access, create, update and delete against one or several objects and one or several fields. Internally these methods check to see if a test is running and if it is simply passes (return true or exit without exception), otherwise it uses the Salesforce API to apply the real CRUD/FLS tests and responds accordingly. NB: We have a way to force the code to apply real CRUD/FLS for the small number of tests we do want CRUD/FLS to be applied in - the tests for this class itself.



                          This approach has some down-sides, the most notable being that the Checkmarx scanner can't see that we do the CRUD/FLS checks, so we have to basically mark every single DML operation and SOQL/SOSL query as being a False Positive and explain that checks were done via our util class in order to pass the security review for our managed package. (BTW, Salesforce has some goodies coming out Winter '20 [with luck] that will make Apex handling of CRUD/FLS much cleaner and easier to implement. However, you'll still want to be able to mock out those new features in unit tests.)



                          The up-side: unit tests behave as if the user has access to everything and every operation.







                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered Jun 25 at 15:30









                          Phil WPhil W

                          1,9361 gold badge3 silver badges11 bronze badges




                          1,9361 gold badge3 silver badges11 bronze badges



























                              draft saved

                              draft discarded
















































                              Thanks for contributing an answer to Salesforce Stack Exchange!


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid


                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.

                              To learn more, see our tips on writing great answers.




                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function ()
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsalesforce.stackexchange.com%2fquestions%2f267194%2fhow-to-test-crud-and-fls-in-unit-tests%23new-answer', 'question_page');

                              );

                              Post as a guest















                              Required, but never shown





















































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown

































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown







                              Popular posts from this blog

                              Category:9 (number) SubcategoriesMedia in category "9 (number)"Navigation menuUpload mediaGND ID: 4485639-8Library of Congress authority ID: sh85091979ReasonatorScholiaStatistics

                              Circuit construction for execution of conditional statements using least significant bitHow are two different registers being used as “control”?How exactly is the stated composite state of the two registers being produced using the $R_zz$ controlled rotations?Efficiently performing controlled rotations in HHLWould this quantum algorithm implementation work?How to prepare a superposed states of odd integers from $1$ to $sqrtN$?Why is this implementation of the order finding algorithm not working?Circuit construction for Hamiltonian simulationHow can I invert the least significant bit of a certain term of a superposed state?Implementing an oracleImplementing a controlled sum operation

                              Magento 2 “No Payment Methods” in Admin New OrderHow to integrate Paypal Express Checkout with the Magento APIMagento 1.5 - Sales > Order > edit order and shipping methods disappearAuto Invoice Check/Money Order Payment methodAdd more simple payment methods?Shipping methods not showingWhat should I do to change payment methods if changing the configuration has no effects?1.9 - No Payment Methods showing upMy Payment Methods not Showing for downloadable/virtual product when checkout?Magento2 API to access internal payment methodHow to call an existing payment methods in the registration form?