#テスト用のデータはTestDataFactoryクラスで作る
TestDataFactoryにテストレコード作成処理を纏めます。
こうすることで、各々のテストクラスで行うテストレコード作成を共通化します。
【サンプルコード】
public with sharing class TestDataFactory {
public static User createTestUser(String name){
Profile profile = getStandardProfile();
String profileId = profile.id;
User user = new User();
user.Email = name + 'test@xx.xxx.com';
user.UserName = name + 'test@xx.xxx.com';
user.LastName = name;
user.Alias = user.UserName.split('@')[0].left(8);
user.ProfileId = profileId;
user.EmailEncodingKey = 'ISO-2022-JP';
user.LanguageLocaleKey = 'ja';
user.LocaleSidKey = 'ja_JP';
user.TimeZoneSidKey = 'Asia/Tokyo';
insert user;
return user;
}
public static Profile getStandardProfile(){
List<Profile> profiles = new List<Profile>();
profiles = [
SELECT Id
FROM Profile
WHERE Name IN ('標準ユーザ','Standard User' )
LIMIT 1];
return profiles[0];
}
public static void assignPermissionSet (Id userId, String permissionSetName){
PermissionSet permissionSet = [SELECT Id FROM PermissionSet WHERE Name = :permissionSetName];
PermissionSetAssignment permissionSetAssignment = new PermissionSetAssignment(PermissionSetId = permissionSet.Id, AssigneeId = userId);
Insert permissionSetAssignment;
}
public static List<Contact> createContactWithAccount( Integer numContacts ){
List<Account> accounts = new List<Account>();
for( Integer i=0; i<numContacts; i++ ){
Account account = new Account(Name='TestAccount' + i);
accounts.add(account);
}
insert accounts;
List<Contact> contacts = new List<Contact>();
for( Integer i=0; i<numContacts; i++ ){
Contact contact = new Contact(LastName='TestContact' + i, Account=accounts[i]);
contacts.add(contact);
}
insert contacts;
return contacts;
}
public static List<Contact> createContactWithoutAccount( Integer numContacts ){
List<Contact> contacts = new List<Contact>();
for( Integer i=0; i<numContacts; i++ ){
Contact contact = new Contact(LastName='TestContact' + i);
contacts.add(contact);
}
insert contacts;
return contacts;
}
public static List<Contact> createDddContactWithAccount( Integer numContacts ){
List<Account> accounts = new List<Account>();
for( Integer i=0; i<numContacts; i++ ){
Account account = new Account(Name='TestAccount' + i);
accounts.add(account);
}
insert accounts;
List<Contact> contacts = new List<Contact>();
for( Integer i=0; i<numContacts; i++ ){
Contact contact = new Contact(LastName='TestContact' + i, Account=accounts[i], LeadSource = 'DDD');
contacts.add(contact);
}
insert contacts;
return contacts;
}
public static List<Contact> createDddContactWithoutAccount( Integer numContacts ){
List<Contact> contacts = new List<Contact>();
for( Integer i=0; i<numContacts; i++ ){
Contact contact = new Contact(LastName='TestContact' + i, LeadSource = 'DDD');
contacts.add(contact);
}
insert contacts;
return contacts;
}
}
#テストメソッド名にルールを
テストメソッドは以下の規則で名前を付けましょう。
名前だけでどのようなテストを行うかを明示的に示します。
【命名規則】
テスト対象のメソッド名_シナリオ_期待される振る舞い
【サンプルコード】
@isTest
static void createNewContact_CorrectParams_ReturnId(){
Account parentAccount = new Account();
parentAccount.Name = 'TestAccount';
parentAccount.Phone = '11111111111';
Contact newContact = new Contact();
newContact.LastName = 'Test';
newContact.FirstName = 'Contact';
ContactApplicationService contactApplicationService = new ContactApplicationService();
Id newContactId;
Test.startTest();
System.runAs(getTestUser()){
newContactId= contactApplicationService.createNewContact(parentAccount,newContact);
}
Test.stopTest();
Contact resultContact = [
SELECT Id
FROM Contact
WHERE Account.Name =: parentAccount.Name AND Account.Phone =: parentAccount.Phone AND LastName =: newContact.LastName AND FirstName =: newContact.FirstName
];
System.assertEquals( newContactId, resultContact.Id );
}
#マジックStringを避ける
マジックStringとはこういった値です。
これだとTestという値がどのような影響を及ぼすかは分かりません。
Id newAccountId = AccountService.create( 'Test' );
ではこれだとどうでしょう?
static final String ACCOUNT_NAME = 'Test';
Id newAccountId = AccountService.create( ACCOUNT_NAME );
Testという値が、取引先オブジェクトの名前であることが直ぐに分かります。
コーディングした人以外にも値の意味が分かるように、定数に値の用途を吹き込みます。
#テスト対象の処理をTest.startTest()とTest.stopTest()で囲む
テストメソッド内の準備で、DML処理やSOQLを発行する事はあるかと思います。
その際、ガバナ制限である、1トランザクションあたりのDML処理上限数やSOQL発行上限数を消化してしまいます。
準備時の消費はテストに換算すべきでないので、Test.startTest()によりリセットします。
Test.stopTest()をつける事も忘れずに。
【サンプルコード】
Test.startTest();
Id newContactId = contactApplicationService.createNewContact(parentAccount,newContact);
Test.stopTest();
#System.runAsでテスト対象のユーザを指定する
System.runAs無しで実行すると、システム実行となり権限を考慮したテストが出来なくなります。
なので、必ずSystem.runAsにてテスト対象のユーザを指定して実行します。
【サンプルコード】
Test.startTest();
System.runAs(getTestUser()){
Id newContactId = contactApplicationService.createNewContact(parentAccount,newContact);
}
Test.stopTest();
#assertEqualsは1テストに1つ
assertEqualsを複数入れてしまうと、何をテストしたいかが不明確になります。
あと、最初のassertEqualsで失敗すると次のassertEqualsが評価されないためテストもし難くなります。