TL;DR
- 主従関係の子レコードを操作すると親の
LastModifiedDateが自動更新される(回避不可) - テストでは
Test.isRunningTest()で環境判定してカスタム項目に切り替える - 本番デプロイ時のコード修正が不要で保守性が高い
問題の背景
バッチ処理でLastModifiedDateを使って前月更新分のデータを抽出する実装をしていたところ、テストデータ作成で問題が発生しました。
やりたかったこと
- 親と子の主従関係
- テストでは過去の
LastModifiedDateを持つテストデータを作成したい
発生した問題
子を作成すると、親のLastModifiedDateが現在時刻に自動更新されてしまう
原因
Salesforceの主従関係では、子レコードの作成・更新・削除時に親のLastModifiedDateが必ず更新される仕様です。
これは標準仕様であり、回避できません。
調査した解決策
環境を自動判定してフィールドを切り替える方法。
実装コード
// キャッシュ用の静的変数
private static Boolean isTestOrSandbox;
private static String dateFieldCache;
private static String getDateField() {
if (dateFieldCache == null) {
// テスト実行中かサンドボックス環境かを判定
if (Test.isRunningTest()) {
isTestOrSandbox = true;
} else {
isTestOrSandbox = [SELECT IsSandbox FROM Organization LIMIT 1].IsSandbox;
}
// 環境に応じてフィールドを切り替え
dateFieldCache = isTestOrSandbox
? 'XXXX__c' // カスタム項目
: 'LastModifiedDate'; // 標準項目
}
return dateFieldCache;
}
この方法のメリット
1. デプロイ時の作業不要
本番環境へのデプロイ時にコードを修正する必要がありません。
環境が自動判定されるため、人的ミスのリスクがゼロです。
2. 継続的なテストが可能
今後の保守開発やコード修正時も、テストクラスをそのまま実行できます。
テストのたびにカスタム項目を追加・削除する手間が不要です。
3. サンドボックスでの検証が容易
サンドボックス環境でも本番と同じコードで検証でき、主従関係の制約を気にせずテストデータを作成できます。
4. 環境ごとの挙動が明確
| 環境 | Test.isRunningTest() | IsSandbox | 使用フィールド |
|---|---|---|---|
| テスト実行時 | true | - | XXXX__c |
| サンドボックス | false | true | XXXX__c |
| 本番環境 | false | false | LastModifiedDate |
注意点
パフォーマンス対策
[SELECT IsSandbox FROM Organization]のクエリは、初回のみ実行されるようキャッシュしています。
カスタム項目の作成
XXXX__cという日時型のカスタム項目を、オブジェクトに作成する必要があります。
まとめ
- 主従関係の
LastModifiedDate問題はSalesforce標準仕様で回避不可 - 環境自動判定によるフィールド切り替えがベストプラクティス
- デプロイ作業不要で保守性が高い
- 本番では
LastModifiedDate、テスト・サンドボックスではXXXX__cを使用
この方法により、主従関係を持つオブジェクトでも安心してバッチ処理のテストができます!