トリガー
trigger ObjectATrigger on ObjectA__c (before insert) {
if (Trigger.isInsert && Trigger.isBefore) {
ObjectAHelper.setDefaultStatus(Trigger.new);
}
}
クラス
public class ObjectAHelper {
private static final String DEFAULT_STATUS = '起票';
public static void setDefaultStatus(List<ObjectA__c> newRecords) {
if (newRecords == null || newRecords.isEmpty()) {
return;
}
for (ObjectA__c record : newRecords) {
record.Status__c = DEFAULT_STATUS;
}
}
}
public class ObjectAHelper {
private static final String REVIEW_STATUS_PENDING = '未レビュー';
/**
* レビュー者が新規に設定された場合、または更新された場合にレビュー状況を未レビューに設定する
* @param newRecords オブジェクトAの新しいレコードリスト
* @param oldRecords オブジェクトAの古いレコードマップ
*/
public static void setReviewStatus(List<ObjectA__c> newRecords, Map<Id, ObjectA__c> oldRecords) {
for (ObjectA__c newRecord : newRecords) {
ObjectA__c oldRecord = oldRecords != null ? oldRecords.get(newRecord.Id) : null;
// 新規登録時:レビュー者が設定されていれば「未レビュー」にする
// 更新時:レビュー者が変更された場合にのみ「未レビュー」にする
if (newRecord.Reviewer__c != null &&
(oldRecord == null || oldRecord.Reviewer__c != newRecord.Reviewer__c)) {
newRecord.ReviewStatus__c = REVIEW_STATUS_PENDING;
}
}
}
}
エラー処理
public class ObjectAHelper {
// エラーメッセージを定数として定義
private static final String ERROR_RESPONSE_DATE_BEFORE_TICKET_DATE = '対応期日は起票日よりも後の日付を設定してください。';
private static final String ERROR_COMPLETION_DATE_BEFORE_TICKET_DATE = '完了日は起票日よりも後の日付を設定してください。';
/**
* オブジェクトAのバリデーションチェック
* 対応期日と完了日に対してバリデーションを行います。
* @param records オブジェクトAのレコードリスト
*/
public static void validateDates(List<ObjectA__c> records) {
for (ObjectA__c record : records) {
validateResponseDate(record);
validateCompletionDate(record);
}
}
// 対応期日のバリデーション
private static void validateResponseDate(ObjectA__c record) {
if (record.ResponseDate__c != null && record.TicketDate__c != null && record.ResponseDate__c < record.TicketDate__c) {
record.ResponseDate__c.addError(ERROR_RESPONSE_DATE_BEFORE_TICKET_DATE);
}
}
// 完了日のバリデーション
private static void validateCompletionDate(ObjectA__c record) {
if (record.CompletionDate__c != null && record.TicketDate__c != null && record.CompletionDate__c < record.TicketDate__c) {
record.CompletionDate__c.addError(ERROR_COMPLETION_DATE_BEFORE_TICKET_DATE);
}
}
}
public class ValidationMessages {
public static final String ERROR_RESPONSE_DATE_BEFORE_TICKET_DATE = '対応期日は起票日よりも後の日付を設定してください。';
public static final String ERROR_COMPLETION_DATE_BEFORE_TICKET_DATE = '完了日は起票日よりも後の日付を設定してください。';
}
public class DateUtils {
/**
* 日付1が日付2より前かどうかを判定
* @param date1 比較する日付1
* @param date2 比較する日付2
* @return 日付1が日付2より前の場合にtrue、そうでない場合はfalse
*/
public static Boolean isBefore(Date date1, Date date2) {
if (date1 == null || date2 == null) {
return false; // いずれかがnullの場合はfalseを返す
}
return date1 < date2;
}
}
public class ObjectAHelper {
/**
* オブジェクトAのバリデーションチェック
* 対応期日と完了日に対してバリデーションを行います。
* @param records オブジェクトAのレコードリスト
*/
public static void validateDates(List<ObjectA__c> records) {
for (ObjectA__c record : records) {
validateResponseDate(record);
validateCompletionDate(record);
}
}
// 対応期日のバリデーション
private static void validateResponseDate(ObjectA__c record) {
if (DateUtils.isBefore(record.ResponseDate__c, record.TicketDate__c)) {
record.ResponseDate__c.addError(ValidationMessages.ERROR_RESPONSE_DATE_BEFORE_TICKET_DATE);
}
}
// 完了日のバリデーション
private static void validateCompletionDate(ObjectA__c record) {
if (DateUtils.isBefore(record.CompletionDate__c, record.TicketDate__c)) {
record.CompletionDate__c.addError(ValidationMessages.ERROR_COMPLETION_DATE_BEFORE_TICKET_DATE);
}
}
}
- 開発コンソールからテストを実行
開発コンソールを開く
Salesforceの設定メニューから「開発コンソール」を選択します。
テストメニューから実行
開発コンソールで[テスト]メニュー > [すべてのテストを実行]を選ぶと、全てのテストクラスが実行されます。 特定のテストクラスのみを実行する場合は、[テスト] > [テストを実行]を選び、実行したいテストクラス(例: DateUtilsTest)を指定して実行します。
テストクラス
@isTest
public class DateUtilsTest {
@isTest
static void testIsBefore() {
Date date1 = Date.newInstance(2023, 1, 1);
Date date2 = Date.newInstance(2023, 1, 2);
Date date3 = Date.newInstance(2023, 1, 1);
// テストケース1: date1がdate2より前の場合(trueを期待)
System.assertEquals(true, DateUtils.isBefore(date1, date2), 'Expected date1 to be before date2');
// テストケース2: date1とdate3が同じ場合(falseを期待)
System.assertEquals(false, DateUtils.isBefore(date1, date3), 'Expected date1 to be equal to date3');
// テストケース3: date2がdate1より後の場合(falseを期待)
System.assertEquals(false, DateUtils.isBefore(date2, date1), 'Expected date2 to be after date1');
// テストケース4: date1がnullの場合(falseを期待)
System.assertEquals(false, DateUtils.isBefore(null, date2), 'Expected result to be false when date1 is null');
// テストケース5: date2がnullの場合(falseを期待)
System.assertEquals(false, DateUtils.isBefore(date1, null), 'Expected result to be false when date2 is null');
// テストケース6: date1とdate2が両方nullの場合(falseを期待)
System.assertEquals(false, DateUtils.isBefore(null, null), 'Expected result to be false when both dates are null');
}
}
@isTest
public class ObjectAHelperTest {
@isTest
static void testValidateDates() {
// TestUtilクラスを使用してテストデータを作成
ObjectA__c record = TestUtil.createObjectARecord(
Date.today(), // 起票日
Date.today().addDays(-1), // 起票日より前の対応期日
Date.today().addDays(-1) // 起票日より前の完了日
);
// テスト開始
Test.startTest();
try {
insert record;
System.assert(false, 'Expected DMLException due to validation errors');
} catch (DmlException e) {
// バリデーションエラーが発生することを確認
System.assertEquals(true, e.getMessage().contains(ValidationMessages.ERROR_RESPONSE_DATE_BEFORE_TICKET_DATE),
'Expected error message for ResponseDate validation');
System.assertEquals(true, e.getMessage().contains(ValidationMessages.ERROR_COMPLETION_DATE_BEFORE_TICKET_DATE),
'Expected error message for CompletionDate validation');
}
Test.stopTest();
}
}
@isTest
public class ObjectAHelperTest {
@isTest
static void testSetDefaultStatus() {
// テストデータの作成: ステータスを未設定でレコードを作成
ObjectA__c record = new ObjectA__c();
// トリガー実行を検証するためにレコードを挿入
Test.startTest();
insert record;
Test.stopTest();
// レコードを再取得して、ステータスが「起票」に設定されているか確認
ObjectA__c insertedRecord = [SELECT Status__c FROM ObjectA__c WHERE Id = :record.Id LIMIT 1];
System.assertEquals('起票', insertedRecord.Status__c, 'Status should be set to 起票 on insert');
}
@isTest
static void testSetDefaultStatusWithExistingStatus() {
// テストデータの作成: ステータスがすでに設定されている場合
ObjectA__c record = new ObjectA__c(Status__c = '対応中');
// トリガー実行を検証するためにレコードを挿入
Test.startTest();
insert record;
Test.stopTest();
// レコードを再取得して、ステータスが変更されていないことを確認
ObjectA__c insertedRecord = [SELECT Status__c FROM ObjectA__c WHERE Id = :record.Id LIMIT 1];
System.assertEquals('対応中', insertedRecord.Status__c, 'Status should remain unchanged if already set');
}
}
@isTest
public class ObjectAHelperTest {
@isTest
static void testSetReviewStatusOnInsert() {
// 新規作成時にレビュー者を設定し、レビュー状況が「未レビュー」になることを確認
ObjectA__c record = new ObjectA__c(Reviewer__c = '005xx000001SvWq'); // サンプルのユーザーID
Test.startTest();
insert record;
Test.stopTest();
// レコードを再取得してレビュー状況を確認
ObjectA__c insertedRecord = [SELECT ReviewStatus__c FROM ObjectA__c WHERE Id = :record.Id LIMIT 1];
System.assertEquals('未レビュー', insertedRecord.ReviewStatus__c, 'ReviewStatus should be set to 未レビュー on insert with Reviewer');
}
@isTest
static void testSetReviewStatusOnUpdate() {
// 既存レコードを作成(レビュー者なし、レビュー状況もなし)
ObjectA__c record = new ObjectA__c();
insert record;
// レコードを更新し、レビュー者を設定
record.Reviewer__c = '005xx000001SvWq'; // サンプルのユーザーID
Test.startTest();
update record;
Test.stopTest();
// レコードを再取得してレビュー状況を確認
ObjectA__c updatedRecord = [SELECT ReviewStatus__c FROM ObjectA__c WHERE Id = :record.Id LIMIT 1];
System.assertEquals('未レビュー', updatedRecord.ReviewStatus__c, 'ReviewStatus should be set to 未レビュー on update with Reviewer');
}
@isTest
static void testReviewStatusNotUpdatedWhenReviewerUnchanged() {
// 初期状態でレビュー者とレビュー状況を設定
ObjectA__c record = new ObjectA__c(Reviewer__c = '005xx000001SvWq', ReviewStatus__c = 'レビュー済み');
insert record;
// 他の項目だけを更新(Reviewer__cは変更しない)
record.SomeOtherField__c = '新しい値';
Test.startTest();
update record;
Test.stopTest();
// レコードを再取得してレビュー状況が変わらないことを確認
ObjectA__c nonUpdatedRecord = [SELECT ReviewStatus__c FROM ObjectA__c WHERE Id = :record.Id LIMIT 1];
System.assertEquals('レビュー済み', nonUpdatedRecord.ReviewStatus__c, 'ReviewStatus should remain レビュー済み if Reviewer is unchanged');
}
}
@isTest
static void testValidateDates() {
// TestUtilクラスを使用してテストデータを作成
ObjectA__c record = TestUtil.createObjectARecord(
Date.today(), // 起票日
Date.today().addDays(-1), // 起票日より前の対応期日
Date.today().addDays(-1) // 起票日より前の完了日
);
// テスト開始
Test.startTest();
try {
insert record;
System.assert(false, 'Expected DMLException due to validation errors');
} catch (DmlException e) {
// 複数のエラーメッセージをフィールドごとに取得
Map<String, List<String>> errors = e.getDmlFieldsAndMessages();
// 各フィールドのエラーメッセージが期待通りか確認
System.assertEquals(true, errors.get('ResponseDate__c')[0].contains(ValidationMessages.ERROR_RESPONSE_DATE_BEFORE_TICKET_DATE),
'Expected error message for ResponseDate validation');
System.assertEquals(true, errors.get('CompletionDate__c')[0].contains(ValidationMessages.ERROR_COMPLETION_DATE_BEFORE_TICKET_DATE),
'Expected error message for CompletionDate validation');
}
Test.stopTest();
}