0

I have a Visualforce page with a custom controller. When clicking one of the buttons, code is being executed and at the end a future method is being called.

public static void clickButton() 
{ 
    //Execute code 
    //Call future method 
}

The logic of the future method contains an insert of a record. Before inserting the record, the FLS of the populated fields is being checked.

The code itself is working fine, but the test code is indicating the user doesn't have access to a field on the record that should be inserted.

In my test code I am creating a user and I assign a permission set to give the user access to the object and the necessary fields. This user is being passed to System.runAs in the tests, so the tests should be run in the context of this user.

I have been debugging the code and it appears the code before the future method is ran in the context of the created user and the logic of the future method is ran as the user who started the test. In this case the user who started the test, doesn't have access to the field. That's why the test fails.

I can solve the failing test easily, but I am wondering about the behaviour during the tests. Is it normal that the synchronous code is being executed as the created user and the asynchronous code as the user who started the test?

Thanks in advance

Edit: the test code has the below structure.

Test.startTest();
System.runAs(crmUser)
{
    PageReference pageRef = Page.page1;
    Test.setCurrentPageReference(pageRef);

    //Init the controller
    PageController myPageController = new PageController();   

    //This method is being executed when the button is clicked.
    //The future call is being done inside this method.     
    myPageController.registerUser();
}
Test.stopTest();
  • Tried with executing System.rusAs(User) – NITHESH K Sep 5 '17 at 7:34
  • @NITHESHK I am already using System.runAs. I pass the created user, yet the future method is being run as the user who started the test and not the created user. – svenf Sep 5 '17 at 7:36
  • make sure code inside Test.startTest(); and Test.stopTest(); enclose only the future method between start and stop test. – NITHESH K Sep 5 '17 at 7:38
0

Using the @future annotation to identify methods that are executed asynchronously. When you specify future, the method executes when Salesforce has available resources.

You need to know this things here.

  • Methods with the future annotation must be static methods, and can only return a void type.

  • Asynchronous calls, such as @future or executeBatch, called in a startTest, stopTest block, do not count against your limits for the number of queued jobs.

  • Use Test.startTest & Test.stopTest around your future method call. stopTest will ensure your future method was called.

Change as below code

System.runAs(crmUser)
{
    PageReference pageRef = Page.page1;
    Test.setCurrentPageReference(pageRef);

    //Init the controller
    PageController myPageController = new PageController();   

    //This method is being executed when the button is clicked.
    //The future call is being done inside this method.     
    Test.startTest(); 
    myPageController.registerUser();
    Test.stopTest();
}
0

As the asynchronous code only executes when Test.stopTest() is called, move that call to inside the System.runAs block (where you have the user changed).

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.