-1

I have written a scheduled apex class and apex job that I want confirm if it works. How can I test/verify it will work as expected without waiting for it to run at its scheduled time for one record and also a number of records?

2
  • 2
    It should be the purpose of a test class. Did you try moking your data and scheduling the job between Test.startTest() and Test.stopTest()?
    – RubenDG
    Commented Mar 21, 2022 at 21:42
  • @RubenDG Thanks. Im not trying to write a test class. I already have that. Let me clarify. We are doing regression testing. So a non technical person wants the job to run to test out the functionality is working. We do not want to wait till 1am when is scheduled to run to verify it before we move it to production. Does that make sense?
    – user58
    Commented Mar 22, 2022 at 9:42

1 Answer 1

2

Creating a unit test class (e.g. @isTest private class MyTest{ /* test things */}) is how you write automated tests (that can/must be run when you deploy new code (or changes to existing code) to a production environment).

As a general rule, you should only test the things that you have control over (and visibility of).

You don't have control over how Salesforce causes Future/Scheduled/Queueable/Batch/Continuations (collectively, our asynchronous execution options) to run, so you shouldn't test that behavior (and instead trust that Salesforce knows and tests how their features work).

What you do have control over, however, is what happens when your code is run asynchronously.

If your method is public, then there's nothing stopping you from calling it directly (and synchronously).

Given the following example class

public class MySchedulable implements Schedulable{
    public static void execute(SchedulableContext ctx){
        // do work
    }
}

A corresponding test class would look something like this

@isTest
private class MySchedulableTest{
    @testSetup
    static void doSetup(){
        // Create and insert any SObject records, Custom Setting records, etc...
        //   that you need for your code to be able to run
    }

    @isTest
    static void execute_TestNormalRun(){
        // Do any test-specific setup here

        // call the code you wish to test directly (if possible)
        Test.startTest();
        // The SchedulableContext doesn't have too much use.
        // It's typical to completely ignore it in the actual method, so we
        //   can usually just pass 'null' into the method.
        // This is calling the method directly, which means that it will be executed
        //   synchronously (except for @future annotated methods)
        MySchedulable.execute(null);
        Test.stopTest();

        // Gather results (which probably means you need to perform a query to
        //   see which SObjects were inserted/updated/deleted) and make assertions
       //   to verify that the results of running your code are what you expected
    }
}

Here, the Test.startTest() and Test.stopTest() aren't usually that important.

When you're writing tests for code that causes asynchronous code to be executed though, they're vital. They cause one level of async execution to be gathered, and then executed synchronously. If your async code isn't run synchronously, they will not be run before the test is over.

Let's say you have the following class

public class MyFutureMethodClass{
    @future
    public static void myFutureMethod(){
        system.debug('@future method run');
    }
}

and you have a client class (i.e. code that uses another class or piece of functionality)

public class FutureClient{
    public void doWork(){
        MyFutureMethodClass.myFutureMethod();
    }
}

You would write test methods for FutureClient like so

@isTest
private class MyFutureClientTest{
    @testSetup
    static void doSetup(){
        // Create and insert SObject records that MyFutureClient requires to run.
    }

    @isTest
    static void doWork_EnsureAsyncCodeRuns(){
        // any test-specific setup here

        Test.startTest();
        MyFutureClient client = new MyFutureClient();

        // Execute the code that causes async work to be requested
        client.doWork();

        // Test.stopTest() causes async work to be run immediately afterwords, which
        //   makes it run synchronously (for this test only)
        Test.stopTest();

        // At this point, the normally async code has been run, and you can
        //   run queries (and the like) to gather the results of that code being run
    }
}
3
  • Thank you. I am not trying to write a unit test. I would to just execute the code for a someone that does testing. So they can verify it works as expected. Is there way to do that without a unit test?
    – user58
    Commented Mar 22, 2022 at 9:45
  • 1
    @user58 The same idea applies outside of unit tests. You call the method directly (via anonymous apex).
    – Derek F
    Commented Mar 22, 2022 at 12:29
  • Thank you that worked.
    – user58
    Commented Mar 22, 2022 at 16:48

You must log in to answer this question.

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