Part 6: テストクラスでのエラーハンドリングとカスタム例外の活用
前回は ガバナ制限を考慮したエラーハンドリング と バッチ処理の例外処理 について解説しました。
今回は テストクラスでのエラーハンドリング と カスタム例外の活用 に焦点を当てます。
1. テストクラスでのエラーハンドリング
Salesforce では、Apex コードの 75% 以上をカバーするテストクラスが必須 です。
特に エラーハンドリングを適切にテストしないと、実際の運用時に問題が発生する可能性 があります。
1.1. System.assertException()
で例外発生を確認
例外が正しくスローされるかを確認するには System.assertException()
を使います。
✅ OK 例: try-catch
のテスト
@isTest
private class SampleTest {
@isTest
static void testExceptionHandling() {
try {
MyClass.methodThatThrowsException();
System.assert(false, '例外が発生するはずなのに、発生しませんでした');
} catch (CustomException e) {
System.assertEquals('エラーメッセージ', e.getMessage());
}
}
}
このテストでは、例外が発生することを前提に System.assertException()
で検証 しています。
1.2. Test.startTest()
/ Test.stopTest()
を使ったテスト
バッチ処理や非同期処理のエラーハンドリングをテストする場合、
Test.startTest()
/ Test.stopTest()
を使って非同期処理を強制実行 します。
✅ OK 例: バッチ処理の例外テスト
@isTest
private class BatchErrorTest {
@isTest
static void testBatchErrorHandling() {
// テストデータ作成
List<Account> accounts = new List<Account>();
for (Integer i = 0; i < 200; i++) {
accounts.add(new Account(Name = 'Test Account ' + i));
}
insert accounts;
// バッチ実行
Test.startTest();
BatchApexExample batch = new BatchApexExample();
Database.executeBatch(batch, 50);
Test.stopTest();
// エラーログを検証
List<ErrorLog__c> logs = [SELECT Message__c FROM ErrorLog__c];
System.assert(logs.size() > 0, 'エラーログが作成されているはず');
}
}
このテストでは、バッチ処理のエラーを再現し、エラーログが作成されることを検証 しています。
2. カスタム例外 (CustomException
) の活用
標準の Exception
だけでなく、カスタム例外を作成するとエラーハンドリングがより明確になります。
2.1. カスタム例外の定義
Apex では extends Exception
を使って独自の例外を作成 できます。
✅ OK 例: カスタム例外 InvalidDataException
public class InvalidDataException extends Exception {}
このように 特定のエラーを識別するためのカスタム例外を定義 できます。
2.2. カスタム例外の活用
データのバリデーション時に InvalidDataException
を使う ことで、
エラーの種類を明確に分けられます。
✅ OK 例: メソッドでカスタム例外をスロー
public class AccountService {
public static void validateAccount(Account acc) {
if (String.isEmpty(acc.Name)) {
throw new InvalidDataException('アカウント名が空です');
}
}
}
この validateAccount()
メソッドは、アカウント名が空なら InvalidDataException
をスロー します。
2.3. カスタム例外を使ったテスト
カスタム例外が 正しく発生することを検証 します。
✅ OK 例: InvalidDataException
のテスト
@isTest
private class AccountServiceTest {
@isTest
static void testValidateAccount() {
try {
Account acc = new Account();
AccountService.validateAccount(acc);
System.assert(false, '例外が発生するはずなのに、発生しませんでした');
} catch (InvalidDataException e) {
System.assertEquals('アカウント名が空です', e.getMessage());
}
}
}
このテストでは、validateAccount()
が正しく例外をスローすることを確認 しています。
3. 例外処理のベストプラクティス
3.1. 例外の種類を明確に分ける
-
DmlException
→ DML 操作の失敗時 (insert/update/delete
のエラー) -
QueryException
→ SOQL クエリのエラー (List has no rows for assignment
) -
LimitException
→ ガバナ制限 (Too many SOQL queries
など) -
CustomException
→ 独自のエラー (InvalidDataException
など)
3.2. try-catch
を使う際のポイント
-
キャッチする例外は最小限にする
NG 例:
try { insert account; } catch (DmlException e) { System.debug('DMLエラー: ' + e.getMessage()); }
Exception e
で全てキャッチしてしまうすべての例外をキャッチすると、本来のエラー原因が分かりにくくなる ため注意。try { insert account; } catch (Exception e) { // すべての例外をキャッチするのは危険 System.debug('エラー: ' + e.getMessage()); }
3.3. バッチ処理で例外を記録
-
エラーが発生したレコードはスキップし、エラーログを記録
global void execute(Database.BatchableContext bc, List<Account> scope) { List<Account> successList = new List<Account>(); for (Account acc : scope) { try { insert acc; successList.add(acc); } catch (DmlException e) { ErrorLog__c log = new ErrorLog__c(Message__c = e.getMessage()); insert log; } } }
まとめ
今回は テストクラスでのエラーハンドリング と カスタム例外の活用 について解説しました。
System.assertException()
を使って例外発生を確認Test.startTest()
/Test.stopTest()
で非同期処理をテスト- カスタム例外 (
CustomException
) を作成し、明確なエラーハンドリング try-catch
で適切に例外をキャッチし、ログを記録
次の Part 7 では、エラーハンドリングの設計パターン (エラーログ管理・リトライ機構) を解説 します!