本記事では、Apexのテストクラスに関する注意事項やサンプルコードなどを記載しています。
テストクラスの標準テンプレート
テストクラスの標準テンプレート(サンプル)
/**--------------------------------------------------------------------------
* プログラム名 :TestClassSample
* 概 要 :xxxのテストクラス
* 作成日 :yyyy.mm.dd
* 作成者 :cclt
*--------------------------------------------------------------------------**/
@isTest(SeeAllData=false)
private class TestClassSample {
static final String DEFAULT_STRING = 'テスト内固定文字列の定義';
//testSetupアノテーションを使ってテストデータを生成
@testSetup
static void initTest(){
TestDataFactory.createTestUsers('標準ユーザ');
}
//テストメソッド
//命名ルール(テストクラスのメソッド名_テストケースNO_処理期待値)
static void testClassMethodXX_TestCase1_GetUserInfo(){
//テスト準備
User runUser = TestDataFactory.createTestUsers('標準ユーザ');
//テスト開始
Test.startTest();
//テスト実行ユーザを指定して実行する場合
System.runAs(runUser){
//test code
}
//テスト終了
Test.stopTest();
//テスト結果検証
System.assert(true);
System.assertEquals('xx' , 'xx');
}
}
テストデータ作成のユーティリティクラス(TestDataFactory.cls)サンプル
テストで利用するユーザを作成する場合には、ユーザ名の命名に注意する必要があります。ご存じの通りSalesforceのユーザ名は全世界で一意の値とする必要があり、テストクラスでユーザを作成する場合も同様です。
毎回テストクラスを作成するたびに一意のユーザ名を命名するのは大変なので、ユーザ名を検証するようなプログラムでない限りは、ランダムに採番した値を利用する共通のテストクラスを用意しておくと便利です。
以下は、指定プロファイルのユーザを生成するメソッドを含むテストユーティリティクラスとなります。
@isTest(SeeAllData=false)
public with sharing class TestDataFactory {
static final String DEFAULT_USER_PROFILE_NAME = '標準ユーザ';
static final String DEFAULT_USER_DOMAIN_NAME = '@xxxtestorg.com';
//プロファイル名を指定してランダムなユーザ名のUserレコードを作成
public static User createTestUsers(String profileName) {
//ユーザプロファイル取得
Profile profile = getProfile(profileName);
//AESキーを16進にして先頭8桁をuidとして定義
Blob b = Crypto.GenerateAESKey(128);
String hex = EncodingUtil.ConvertTohex(b);
String uid = hex.SubString(0,8);
User user = new User();
user.Alias = uid;
user.Email= uid + DEFAULT_USER_DOMAIN_NAME;
user.EmailEncodingKey='UTF-8';
user.LastName=uid;
user.LanguageLocaleKey='ja';
user.LocaleSidKey='ja_JP';
user.ProfileId = profile.Id;
user.TimeZoneSidKey='Asia/Tokyo';
user.UserName= uid + DEFAULT_USER_DOMAIN_NAME;
insert user;
return user;
}
//プロファイルが未指定の場合デフォルトのプロファイルをセット
public static Profile getProfile(String profileName){
if( String.isBlank(profileName) ){
profileName = DEFAULT_USER_PROFILE_NAME;
}
Profile profile = new Profile();
profile = [ SELECT Id, Name FROM Profile WHERE Name = :profileName LIMIT 1];
return profile;
}
}
実行結果
以下のような簡単なテストクラスを作成して、testSetupからテスト用のユーザを作成した結果のデバッグログです。
@isTest
private class MyTestClass {
@testSetup
static void initTest(){
TestDataFactory.createTestUsers(null);
}
}
以下、デバッグログ
|USER_DEBUG|[15]|DEBUG|:Blob:Blob[16]
|USER_DEBUG|[17]|DEBUG|:hex:feb46887a6b4124bf97aaea120ab8c9b
|USER_DEBUG|[19]|DEBUG|:uid:feb46887
|USER_DEBUG|[31]|DEBUG|:user:User:{Alias=feb46887, Email=feb46887@xxxtestorg.com, EmailEncodingKey=UTF-8, LastName=feb46887, LanguageLocaleKey=ja, LocaleSidKey=ja_JP, ProfileId=00e5h0000032ZSgAAM, TimeZoneSidKey=Asia/Tokyo, Username=feb46887@xxxtestorg.com, Id=0055h000004JDHEAA4}
テストデータ作成時の注意事項
テストデータとして利用できる組織データ
デフォルトでは、Apex テストメソッド (API バージョン 24.0 以降) は、標準オブジェクト、カスタムオブジェクト、カスタム設定データなどの既存の組織データにはアクセスできません。アクセスできるのは、テストメソッドが作成したデータのみです。ただし、組織またはメタデータオブジェクトの管理に使用する次のようなオブジェクトなどは、そのままテストでアクセスできます。
以下については、テストデータを作成しなくてもテスト実行組織に登録されているデータを参照して利用することができます。
- User
- Profile
- Organization
- CronTrigger
- RecordType
- ApexClass
- ApexTrigger
- ApexComponent
- ApexPage
ただし組織のデータを利用するとテスト実行時の状況によってテスト結果に影響を及ぼしてしまうため、可能な限りテストデータはテストクラス、メソッド毎に用意することが推奨されています。
テストクラスで利用可能な@アノテーション
テストクラスで利用可能なアノテーションについて説明します。
@testSetup
テスト設定メソッドであるtestSetupアノテーションを利用したメソッドは、テストの最初に実行されます。注意事項は以下の通り。
テスト設定メソッドで作成されたレコードは、テストクラス内のすべてのテストメソッドで使用でき、テストクラス実行終了時にロールバックされます。レコード項目の更新やレコード削除など、テストメソッドがこれらのレコードを変更した場合、その変更は、各テストメソッドの実行終了後にロールバックされます。次に実行されるテストメソッドは、元の変更されていない状態のレコードにアクセスできます。
テスト設定メソッドは、テストクラスのデフォルトのデータ分離モードでのみサポートされます。テストクラスまたはテストメソッドが @isTest(SeeAllData=true) アノテーションを使用することで組織データにアクセスできる場合、そのクラスではテスト設定メソッドはサポートされません。テストのためのデータ分離を使用できるのは API バージョン 24.0 以降であるため、テスト設定メソッドを使用できるのもこれらのバージョンのみです。
出典:Salesforce公式Apex開発者ガイド「TestSetup アノテーション」より
【構文例】
@isTest
private class MyTestClass {
@testSetup
static void initTest(){
TestDataFactory.createTestUsers(null);
}
}
@TestVisible
TestVisibleアノテーションを使用すると、テストクラスでないクラスのprivae非公開メンバーまたは保護メンバーにテストメソッドからアクセスすることができるようになります。注意事項は以下の通り。
【構文例】
@isTest
public class TestVisibleMethodSample {
// 非公開のメンバー変数
@TestVisible private static String prefix = 'Prefix';
// 非公開のメソッド
@TestVisible
private static void updateAccount(String name) {
//処理コード
}
}
(テストクラスからの呼び出し)
@isTest
private class TestVisibleMethodTest {
@isTest static void case_doUpdateAccount_fail() {
// TestVisibleアノテーションのメンバーにアクセスする
String prefix = TestVisibleMethodSample.prefix;
System.assertEquals('Prefix', prefix);
// TestVisibleアノテーションのメソッドにアクセスする
TestVisibleMethodSample.updateAccount(prefix);
}
}
テスト関連トピック
指定ユーザでテストを実行する
System.runAs(uid)メソッドを利用することで、uidで指定されてユーザの権限でテストを実行することが可能。詳細は以下参照。
//テスト実行ユーザを指定して実行する場合 ※uidにユーザのIDを指定
System.runAs(uid){
//test code
}
Salesforce公式 Apex開発者ガイド「runAs メソッドの使用」