Skip to main content

Apex 테스트용 테스트 데이터 생성

학습 목표

이 유닛을 완료하면 다음을 수행할 수 있습니다.

  • 테스트 유틸리티 클래스를 만들 수 있습니다.
  • 테스트 유틸리티 메서드를 사용하여 다양한 테스트 케이스에 대한 테스트 데이터를 설정할 수 있습니다.
  • 클래스의 모든 테스트 메서드를 실행할 수 있습니다.
참고

참고

한국어로 학습하시겠어요? 이 배지에서는 Trailhead 실습과제 검증이 영어로 진행됩니다. 참조용 번역이 괄호로 제공됩니다. 영문으로 표시된 값을 복사하여 붙여 넣은 다음 Trailhead Playground 언어를 영어로, 로캘을 미국으로 전환하세요. 여기에 나와 있는 지침을 따르세요.

원하는 언어로 Trailhead 사용하기 배지를 확인해 현지화된 Trailhead 경험을 활용하는 방법을 알아보세요.

Apex 테스트용 테스트 데이터 생성

테스트 유틸리티 클래스를 사용하여 테스트 데이터 설정에 재사용 가능한 메서드를 추가할 수 있습니다.

전제 조건

아직 수행하지 않은 경우 이전 유닛인 Apex 트리거 테스트의 전제 조건을 완료합니다.

테스트 유틸리티 클래스 추가

테스트 데이터 생성을 유틸리티 클래스 메서드에 대한 호출로 대체하여 이전 테스트 메서드를 리팩토링해 보겠습니다. 먼저 테스트 유틸리티 클래스를 만들어야 합니다.

TestDataFactory 클래스는 특별한 유형의 클래스이며, 이는 @isTest라고 주석이 추가된 공개 클래스로 실행 중인 테스트에서만 액세스할 수 있습니다. 테스트 유틸리티 클래스에는 테스트 데이터 설정과 같은 유용한 작업을 수행하기 위해 테스트 메서드에서 호출할 수 있는 메서드가 포함되어 있습니다. 테스트 유틸리티 클래스는 조직의 코드 크기 제한에서 제외됩니다.

TestDataFactory 클래스에 추가하려면 다음 단계를 수행하세요.

  1. Developer Console에서 File(파일) | New(새로 만들기) | Apex Class(Apex 클래스)를 클릭하고 클래스 이름에 대해 TestDataFactory를 입력한 다음 OK(확인)를 클릭합니다.
  2. 기본 클래스 본문을 다음으로 바꿉니다.
    @isTest
    public class TestDataFactory {
      public static List<Account> createAccountsWithOpps(Integer numAccts, Integer numOppsPerAcct) {
        List<Account> accts = new List<Account>();
        for(Integer i=0;i<numAccts;i++) {
          Account a = new Account(Name='TestAccount' + i);
          accts.add(a);
        }
        insert accts;
        List<Opportunity> opps = new List<Opportunity>();
        for(Integer j=0;j<numAccts;j++) {
          Account acct = accts[j];
          // For each account just inserted, add opportunities
          for(Integer k=0;k<numOppsPerAcct;k++) {
            opps.add(new Opportunity(Name=acct.Name + ' Opportunity ' + k,
              StageName='Prospecting',
              CloseDate=System.today().addMonths(1),
              AccountId=acct.Id));
          }
        }
        // Insert all opportunities for all accounts.
        insert opps;
        return accts;
      }
    }

이 테스트 유틸리티 클래스에는 하나의 정적 메서드 createAccountsWithOpps()가 포함되어 있으며, 계정 개수(numAccts 매개변수) 및 각 계정에 대해 생성할 관련 기회 개수(numOppsPerAcct 매개변수)를 허용합니다. 메서드의 첫 번째 루프는 지정된 수의 계정을 생성하고 accts 목록 변수에서 이러한 계정을 저장합니다. 첫 번째 루프 후, insert() DML 문은 데이터베이스의 목록에 있는 모든 계정을 생성하기 위해 호출됩니다.

두 번째 루프는 기회를 만듭니다. 각 기회 그룹이 하나의 계정에 연결되어 있으므로 외부 루프는 계정을 반복하고 현재 계정에 대한 관련 기회를 생성하는 중첩 루프를 포함합니다. 다음에 중첩 루프가 실행될 때 기회는 add() 메서드를 사용하여 동일한 목록에 추가됩니다. 기회는 AccountId 필드를 사용하여 상위 계정에 연결됩니다. 생성된 모든 기회의 총 수는 기회 개수와 계정 개수(numOppsPerAcct*numAccts의 제곱값입니다. 다음으로, insert() DML 문은 루프 외부에서 효율적으로 호출되어 호출 한 번으로 모든 계정에 대한 컬렉션의 모든 기회를 생성합니다.

마지막으로 이 메서드는 새 계정 목록을 반환합니다.

참고

이 방법이 관련된 기회를 반환하지 않더라도 Apex 트리거 테스트의 트리거에 사용된 쿼리와 같이 Account와 Opportunity 간의 기존 관계를 활용하는 SOQL 쿼리를 작성하여 해당 레코드를 가져올 수 있습니다.

테스트 데이터 생성을 위한 유틸리티 메서드 호출

이제 테스트 유틸리티 클래스를 추가했으므로 이 클래스를 활용하도록 TestAccountDeletion 테스트 클래스를 수정합니다. TestDataFactory.createAccountsWithOpps(1,1) 호출에 의해 반환된 배열에는 하나의 Account sObject가 포함됩니다.

다음은 수정된 테스트 메서드입니다. 더 짧은 버전입니다.

@isTest

private class TestAccountDeletion {

  @isTest

  static void TestDeleteAccountWithOneOpportunity() {

    // Test data setup

    // Create one account with one opportunity by calling a utility method

    Account[] accts = TestDataFactory.createAccountsWithOpps(1,1);

    // Perform test

    Test.startTest();

      Database.DeleteResult result = Database.delete(accts[0], false);

    Test.stopTest();

    // Verify that the deletion should have been stopped by the trigger,

    // so check 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());

  }

}

다양한 조건에 대한 테스트

하나의 테스트 메서드로는 트리거에 대해 가능한 모든 입력을 테스트하기에 충분하지 않습니다. 기회가 없는 계정이 삭제되는 경우와 같은 몇 가지 다른 조건을 테스트해야 합니다. 또한 단일 레코드 대신 대량 레코드를 사용하여 동일한 시나리오를 테스트해야 합니다. 다음은 세 가지 추가 테스트 메서드가 포함된 테스트 클래스의 업데이트된 버전입니다. 이 업데이트된 버전의 클래스를 저장합니다.

@isTest

private class TestAccountDeletion {

  @isTest

  static void TestDeleteAccountWithOneOpportunity() {

    // Test data setup

    // Create one account with one opportunity by calling a utility method

    Account[] accts = TestDataFactory.createAccountsWithOpps(1,1);

    // Perform test

    Test.startTest();

      Database.DeleteResult result = Database.delete(accts[0], false);

    Test.stopTest();

    // Verify that the deletion should have been stopped by the trigger,

    // so check 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());

  }

  @isTest

  static void TestDeleteAccountWithNoOpportunities() {

    // Test data setup

    // Create one account with no opportunities by calling a utility method

    Account[] accts = TestDataFactory.createAccountsWithOpps(1,0);

    // Perform test

    Test.startTest();

      Database.DeleteResult result = Database.delete(accts[0], false);

    Test.stopTest();

    // Verify that the deletion was successful

    System.assert(result.isSuccess());

  }

  @isTest

  static void TestDeleteBulkAccountsWithOneOpportunity() {

    // Test data setup

    // Create accounts with one opportunity each by calling a utility method

    Account[] accts = TestDataFactory.createAccountsWithOpps(200,1);

    // Perform test

    Test.startTest();

      Database.DeleteResult[] results = Database.delete(accts, false);

    Test.stopTest();

    // Verify for each record.

    // In this case the deletion should have been stopped by the trigger,

    // so check that we got back an error.

    for(Database.DeleteResult dr : results) {

      System.assert(!dr.isSuccess());

      System.assert(dr.getErrors().size() > 0);

      System.assertEquals('Cannot delete account with related opportunities.',

        dr.getErrors()[0].getMessage());

    }

  }

  @isTest

  static void TestDeleteBulkAccountsWithNoOpportunities() {

    // Test data setup

    // Create accounts with no opportunities by calling a utility method

    Account[] accts = TestDataFactory.createAccountsWithOpps(200,0);

    // Perform test

    Test.startTest();

      Database.DeleteResult[] results = Database.delete(accts, false);

    Test.stopTest();

    // For each record, verify that the deletion was successful

    for(Database.DeleteResult dr : results) {

      System.assert(dr.isSuccess());

    }

  }

}

모든 테스트 메서드 실행

마지막 단계는 테스트 클래스에서 테스트 메서드를 실행하며, 이제 클래스에 더 포괄적인 테스트가 포함되고 테스트 데이터 팩토리를 사용하도록 리팩토링되었습니다. TestAccountDeletion 클래스에서 이미 테스트를 실행했으므로 이 테스트 클래스를 다시 실행하여 모든 테스트 메서드를 실행할 수 있습니다.

  1. 동일한 테스트 실행을 실행하려면 Tests(테스트) 탭을 클릭하고 테스트 실행을 선택한 다음 Test(테스트) | Rerun(재실행)을 클릭합니다.
  2. 최신 테스트 실행을 확장하여 Tests(테스트) 탭에서 결과를 확인합니다. 테스트 실행은 네 가지 테스트가 모두 통과되었음을 보고해야 합니다.

리소스

계속해서 무료로 학습하세요!
계속 진행하려면 계정을 가입하세요.
얻을 수 있는 이점
  • 커리어 목표에 대한 개인화된 권장 사항 제공받기
  • 실습 과제 및 퀴즈를 통해 스킬 연습
  • 진행 상황을 추적하고 고용주에게 공유
  • 멘토십과 커리어 기회에 연결