0

I was doing the trailhead schedulable module and I was able to get all the points for the trail, but when I ran the unit test for it with my assertion, I was getting some strange behavior.

Here is the class:

global class DailyLeadProcessor implements Schedulable {

    global void execute(SchedulableContext sc) {
        List<Lead> recordsToUpdate = new List<Lead>();
        List<Lead> leadList = [select Id, LeadSource from Lead where LeadSource = null limit 200];
        if(!leadList.isEmpty()) {
          for(Lead l : leadList) {
              l.LeadSource = 'Dreamforce';
              recordsToUpdate.add(l);
          }
      }
        update recordsToUpdate;
    }
}

Here is the test class:

@isTest
private class DailyLeadProcessorTest {

    static List<Lead> testLeads;

    @testSetup
    static void initialize() {
        testLeads = new List<Lead>();
        for(Integer i=0; i<200; i++) {
            testLeads.add(new Lead(lastname = 'Smith'+i, company = 'Acme'+i));
        }
        insert testLeads;
        system.assertEquals(200, testLeads.size());
        for(Lead l : testLeads) {
            system.assertNotEquals(null, l.Id);
            system.assertEquals(null, l.LeadSource);
        }
    }

    static testMethod void testSchedulableDailyLeadProcessor() {
        initialize();
        system.assertEquals(200, testLeads.size());
        //[seconds][minutes][hours][Day_of_Month][Month][Day_of_Week][Optional_Year]
        String sch = '0 0 0 15 3 ? 2022';

        test.startTest();
          Id jobId = system.schedule('LeadSchedulerTest', sch, new DailyLeadProcessor());
          List<Lead> leadsBefore = [select Id from Lead where LeadSource = null AND Id in: testLeads];
          system.assertEquals(200, leadsBefore.size(),'all leads with leadSource are not null');
        test.stopTest();

        List<Lead> leadsAfter = [select Id, LeadSource from Lead where Id in: testLeads];
        for(Lead l : leadsAfter) {
          //system.assertEquals('Dreamforce', l.LeadSource,'LeadSource does not contain correct value');
        }
    }
}

The first strange behavior I encountered was the query that shows the count of leads before the process runs. I was getting a count of 400 instead of 200? I added the additional criteria of AND ID IN: testLeads and then the size of the list was 200, but I have no clue where those other 200 records came from. There are only 200 records that are created in the test class and there are only 22 leads that are in the trailhead playground org? So, I don't know where the other 200 records came from?

Secondly, the assertion for the leadsAfter list kept failing with some of the records indicating that LeadSource was null. The class was covered at 100% so I can't identify why some records were indicating LeadSource was null, when it should have the value Dreamforce which is what the schedulable class does.

I ran the check for the module and got the 500 points after commenting out the assertion, but I'm still wondering if there is anything wrong with the code? Or, is it something I didn't catch or is this some odd bug in the org? Anyone else seen this happen or encounter something similar?

1
  • Also your assertions should be after stop methods, as scheduled jobs are collected and run synchronously post test.stopTest() method.
    – MandyKool
    Commented Jul 11, 2018 at 23:43

2 Answers 2

0

So from what I can see, your assertion that is failing is not placed at a point when the Schedulable class may have already run. Just calling the Schedule class in the test method doesn't mean that it has run. If you are going to perform assertions on data that was modified via Schedulable, Queueable, or Batchable you should perform your query and assertions after the Test.stopTest() has been called. When you use Test.startTest() and Test.stopTest() you are enforcing that all modules will have been executed ( not just constructed ) before the test case exits the Test.stopTest() method call. Performing assertions after this method call will now get updated data.

Methods notated with @TestSetup will be run before each test method within the test class and will not need to be called manually. So with that said, your @TestSetup initialize() method was called originally and then when you manually called it again, your static list of 200 Leads now has been doubled.

A better structured test class would look like:

    @isTest
    private class DailyLeadProcessorTest {


        @testSetup
        static void initialize() {
            List<Lead> testLeads = new List<Lead>();
            for(Integer i=0; i<200; i++) {
                testLeads.add(new Lead(lastname = 'Smith'+i, company = 'Acme'+i));
            }
            insert testLeads;

            System.assertEquals(200, testLeads.size());

            for(Lead l : testLeads) {
                System.assertNotEquals(null, l.Id);
                System.assertEquals(null, l.LeadSource);
            }
        }

        static testMethod void testSchedulableDailyLeadProcessor() {
            List<Lead> testLeads = [ SELECT Id FROM Lead ];     
            System.assertEquals(200, testLeads.size());

            //[seconds][minutes][hours][Day_of_Month][Month][Day_of_Week][Optional_Year]
            String sch = '0 0 0 15 3 ? 2022';

            List<Lead> leadsBefore = [SELECT Id FROM Lead WHERE LeadSource = null AND Id in: testLeads];
            System.assertEquals( 200, leadsBefore.size() );

            test.startTest();

            Id jobId = System.schedule('LeadSchedulerTest', sch, new DailyLeadProcessor());

            test.stopTest();


            List<Lead> leadsAfter = [SELECT Id, LeadSource FROM Lead WHERE Id in: testLeads];
            System.assertNotEquals( 0, leadsAfter.size() );

            for(Lead l : leadsAfter) {
              System.assertEquals( 'Dreamforce', l.LeadSource );
            }
        }
    }
1

Looking at your code, I can see you are calling initialize() Method. I dont think that is required as @testSetup methods run by default.

In you test method you just need to query the data.

link to documentation

Also static variables are cleared out with each test method run. These are the two reasons why you are facing this "strange" behavior.

static variables and testSetup

You must log in to answer this question.

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