0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

apexトリガーmemo

Last updated at Posted at 2024-11-11
トリガー
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);
        }
    }
}


  1. 開発コンソールからテストを実行
    開発コンソールを開く
    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();
}

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?