0

I have a piece of scheduled apex that runs once a month, but behaves differently depending on the month. In attempting to write unit tests the unit test triggers the scheduled apex, but does not do so using the assigned cron expression parameters.

This is in my test class...

public static string m_cron = '0 0 1 1 2 ?';
Test.startTest();

String jobId = System.schedule('ScheduleApexClassTest',  m_cron, new eoscheduling());

Test.stopTest();

However, it's clear this is not actually running as if it was Feb 1st - im still getting results as if it was running right now.

2

Framing your System.schedule() invocation with Test.startTest()/Test.stopTest() ensures that your scheduled Apex will run synchronously, but it doesn't change the system clock to ensure that your cron job would "naturally" execute based on that clock time.

If your scheduled job is inspecting the date to determine its own behavior, writing a thorough unit test for that class might call for injecting that dependency through a tiny helper class that'd return an enum defining the appropriate behavior for the context. You could then supply a testing-only mock version of this class to return the behavior that you want to test.

For example, your dependency helper could look like, in normal mode:

public class DateInspector {
    public Behavior getBehavior() {
        if (Date.today().getMonth() == 2) {
           return FEBRUARY_BEHAVIOR;
        } .... and so on
    }
}

And in test mode:

private class TestModeDateInspector {
    private Behavior mode;
    public TestModeDateInspector(Behavior desired_mode) {
       mode = desired_mode;
    }

    public Behavior getBehavior() {
        return mode;
    }
}

You can define an interface that both classes implement (with the method getBehavior()), and define a standard and test-mode constructor for your scheduled class:

public ScheduledClass() {
    return ScheduledClass(new DateInspector());
}

public ScheduledClass(DateInspectorInterface di) {
    myDateInspector = di;
}

Then, your scheduled class calls myDateInspector to determine its desired behavior, and your test class can control this by injecting its TestModeDateInspector set to the desired behavior type with the second constructor.

| improve this answer | |

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.