(小ネタ)SalesforceのスケジュールBatch開発テストでハマりそうになった話

SalesforceでスケジュールBatchクラスのテストコードを書いていた時にハマりそうになった話です。
2018.04.06

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

こんにちは、HOMELAND第7シーズンをFire TV StickでdTVのFOXチャンネルリアルタイム配信を観る時にやたら手こずる井手です。
先日SalesforceのスケジュールBatch開発を行っていた時にテストで危うくハマりそうになったのでご紹介いたします。

想定していた事

スケジュールクラスに対して以下のようなテストコードを想定していました。

schedule_batchTest.cls

  @isTest
  static void test() {
      Test.startTest();
          String jobId = System.schedule('スケジュール実行', 0 0 * * * ?, new sample_batch());
      Test.stopTest();
      // assert処理
  }

しかし、こちらのコードだとBatchクラスのstartメソッドが呼ばれずassertに失敗してしまいました。 実際過去開発を行っていた時は上記コードで問題になることはなく(多分・・記憶ベース)、また例えば
「Salesforce Schedule Batch」等で検索すると上記同様の書き方が紹介されていたりします。
なので、他の箇所がおかしいのかも・・?と色々調べてハマりそうになりました。

解決方法

調べてもあまりこの点情報が無かったのですが、Salesforce Stack Exchangeの記事や以下のTrailheadに記載を見て解決しました。

Test.startTest();
// Schedule the test job
String jobId = System.schedule('ScheduledApexTest',
    CRON_EXP, 
    new RemindOpptyOwners());         
// Verify the scheduled job has not run yet.
List<Task> lt = [SELECT Id 
    FROM Task 
    WHERE WhatId IN :opptyIds];
System.assertEquals(0, lt.size(), 'Tasks exist before job has run');
// Stopping the test will run the job synchronously
Test.stopTest();

Apex スケジューラを使用したジョブのスケジュールより一部引用

Verify the scheduled job has not run yet.」・・な、なんだってー!
どうやら明示的にBatchを呼ばないとテストは出来ないようですね。
なので以下のような処理を加えBatchは別でテストを行いました。

Test.startTest();
    sample_batch batch = new sample_batch();
    Id batchId = Database.executeBatch(batch, 200);
Test.stopTest();

仕様が変わったのか、疑問だったのでAPIバージョン下げてみましたがやはり動かず、知らなかっただけでそもそもの仕様が上記なのかもと疑心暗鬼になりました。。
この辺り公式の発表が見当たりませんでしたのであれば教えて頂きたいなと思います。
※参考にしたStack Exchangeのページにはコメントで「Confirm (API v40): a batch job scheduled with System.schedule is not executed unless the explicit execute() call in a test class.」とあったんですが公式的な記載はみつけられませんでした。

参考とさせて頂いたページ

Apex スケジューラを使用したジョブのスケジュール
How to test a scheduler which runs a batch?