Apex 트리거 테스트
학습 목표
이 유닛을 완료하면 다음을 수행할 수 있습니다.
- 단일 레코드 작업에서 발생하는 트리거에 대한 테스트를 작성할 수 있습니다.
- 클래스의 모든 테스트 메서드를 실행할 수 있습니다.
Apex 트리거 테스트
트리거를 배포하기 전에 트리거를 실행하고 예상 결과를 확인하는 작업을 수행하는 유닛 테스트를 작성합니다.
Apex 트리거 모듈에서 작업한 트리거를 테스트해 보겠습니다. 계정 레코드에 관련 기회가 있는 경우 AccountDeletion
트리거는 레코드 삭제를 방지합니다.
전제 조건
AccountDeletion
트리거를 아직 추가하지 않은 경우 다음 단계를 수행하세요.
- Developer Console에서 File(파일) | New(새로 만들기) | Apex Trigger(Apex 트리거)를 클릭합니다.
- 트리거 이름에
AccountDeletion
을 입력한 다음 sObject에 대한 Account(계정)를 선택합니다. Submit(제출)을 클릭합니다. - 기본 코드를 다음으로 바꿉니다.
trigger AccountDeletion on Account (before delete) { // Prevent the deletion of accounts if they have related opportunities. for(Account a : [SELECT Id FROM Account WHERE Id IN (SELECT AccountId FROM Opportunity) AND Id IN :Trigger.old]) { Trigger.oldMap.get(a.Id).addError('Cannot delete account with related opportunities.'); } }
이전 유닛에서 AccountDeletion
트리거를 추가한 경우 시스템이 과제를 확인할 수 있도록 비활성화하고 다시 활성화합니다.
- Setup(설정)에서
Apex Triggers
를 검색합니다. - Apex Triggers(Apex 트리거) 페이지에서
AccountDeletion
트리거 옆에 있는 Edit(편집)을 클릭합니다. - Is Active(활성)를 선택합니다.
- Save(저장)를 클릭합니다.
조직에 AddRelatedRecord
, CalloutTrigger
또는 HelloWorldTrigger
를 호출한 이전 유닛의 트리거를 포함한 경우 비활성화합니다. 예를 들어 AddRelatedRecord
트리거를 비활성화하려면 다음 단계를 수행하세요.
- Setup(설정)에서
Apex Triggers
를 검색합니다. - Apex Triggers(Apex 트리거) 페이지에서
AddRelatedRecord
트리거 옆에 있는 Edit(편집)을 클릭합니다. - Is Active(활성)를 선택 해제합니다.
- Save(저장)를 클릭합니다.
HelloWorldTrigger
를 비활성화하고 CalloutTrigger
트리거를 비활성화하려면 이전 단계를 반복합니다.
유닛 테스트 추가 및 실행
먼저 테스트 메서드를 추가하는 것으로 시작하겠습니다. 이 테스트 메서드는 트리거가 수행하도록 설계된 작업(양성인 경우)을 확인합니다. 관련 기회가 있는 경우 계정이 삭제되는 것을 방지합니다.
- Developer Console에서 File(파일) | New(새로 만들기) | Apex Class(Apex 클래스)를 클릭합니다.
- 클래스 이름에
TestAccountDeletion
을 입력한 다음 OK(확인)를 클릭합니다. - 기본 클래스 본문을 다음으로 바꿉니다.테스트 메서드는 먼저 기회가 있는 테스트 계정을 설정합니다. 다음으로
@isTest private class TestAccountDeletion { @isTest static void TestDeleteAccountWithOneOpportunity() { // Test data setup // Create an account with an opportunity, and then try to delete it Account acct = new Account(Name='Test Account'); insert acct; Opportunity opp = new Opportunity( Name=acct.Name + ' Opportunity', StageName='Prospecting', CloseDate=System.today().addMonths(1), AccountId=acct.Id); insert opp; // Perform test Test.startTest(); Database.DeleteResult result = Database.delete(acct, false); Test.stopTest(); // Verify // In this case the deletion should have been stopped by the trigger, // so verify that we got back an error. System.assert(!result.isSuccess()); System.assert(result.getErrors().size() > 0); System.assertEquals('Cannot delete account with related opportunities.', result.getErrors()[0].getMessage()); } }
AccountDeletion
트리거를 실행하는 테스트 계정을 삭제합니다. 테스트 메서드는Database.delete()
호출의 반환값을 확인하여 트리거가 테스트 계정 삭제를 방지했는지 확인합니다. 반환값은 삭제 작업에 대한 정보가 포함된Database.DeleteResult
개체입니다. 테스트 메서드는 삭제가 성공하지 않았는지 확인하고 얻은 오류 메시지를 확인합니다. - 이 테스트를 실행하려면 Test(테스트) | New Run(새로운 실행)을 클릭합니다.
- Test Classes(테스트 클래스)에서 TestAccountDeletion을 클릭합니다.
- 테스트 실행에
TestAccountDeletion
클래스의 모든 메서드를 추가하려면 Add Selected(선택 항목 추가)를 클릭합니다. - Run(실행)을 클릭합니다. 최신 실행 아래의 Tests(테스트) 탭에서 테스트 결과를 찾습니다.
TestAccountDeletion
테스트 클래스에는 단일 계정 레코드를 테스트하는 테스트 메서드가 하나만 포함되어 있습니다. 또한 이 테스트는 양성인 경우입니다. 기회가 없는 계정 삭제 및 대량 계정 삭제를 포함하여 모든 경우에 트리거가 작동하는지 확인하기 위해 더 많은 시나리오를 항상 테스트합니다.
테스트 데이터는 테스트 메서드 내부에 설정되며 테스트 메서드를 추가할수록 시간이 오래 걸릴 수 있습니다. 테스트 메서드가 많은 경우 테스트 데이터 생성을 테스트 유틸리티 클래스에 넣고 여러 테스트 메서드에서 유틸리티 클래스를 호출합니다. 다음 유닛에서는 테스트 유틸리티 클래스를 활용하고 더 많은 테스트 메서드를 추가하는 방법을 보여줍니다.
추가 정보
테스트 메서드에는 Test.startTest()
및 Test.stopTest()
메서드 쌍이 포함되며, 이러한 메서드 쌍은 새로운 거버너 제한 집합을 가져오는 코드 블록을 구분합니다. 이 테스트에서 테스트 데이터 설정은 테스트가 수행되기 전에 두 개의 DML 문을 사용합니다. Apex 코드가 거버너 제한 내에서 실행되는지 테스트하려면 데이터 설정의 제한 사용량을 테스트의 제한 사용량과 분리합니다. 데이터 설정 프로세스의 사용 제한을 분리하려면 Test.startTest()
및 Test.stopTest()
블록 내에서 테스트 호출을 종료합니다. 또한 비동기 Apex를 테스트할 경우 이 테스트 블록을 사용합니다. 자세한 내용은 Limits, startTest 및 stopTest 사용을 참조하세요.
리소스
실습 과제 준비하기
이 유닛에 대한 실습 과제를 완료하려면 연락처 개체에서 아래의 코드가 포함된 RestrictContactByName
이라는 Apex 트리거를 생성해야 합니다.
trigger RestrictContactByName on Contact (before insert, before update) { //check contacts prior to insert or update for invalid data for(Contact c : Trigger.New) { if(c.LastName == 'INVALIDNAME') { //invalidname is invalid c.AddError('The Last Name "'+c.LastName+'" is not allowed for DML'); } } }