Salesforce Apex のテストにおけるアサーションと System.runAs() の活用
Apex のテストでは、アサーション (Assertion) を使用して実行結果を検証 します。また、System.runAs() を使ったセキュリティテスト や、混合 DML エラーの回避 についても解説します。
1. アサーションを使用した実行結果の検証
アサーションとは?
アサーションは、テストの期待値と実際の結果を比較して、正しく動作しているかを確認する ためのものです。Apex では System クラスのメソッドを使ってアサーションを行います。
1.1 System クラスのアサーション一覧
| メソッド | 説明 |
|---|---|
System.assert(condition) |
condition が true であることを検証 |
System.assert(condition, message) |
condition が true でない場合、message を表示 |
System.assertEquals(expected, actual) |
expected と actual が等しいことを検証 |
System.assertEquals(expected, actual, message) |
expected と actual が等しくない場合、message を表示 |
System.assertNotEquals(unexpected, actual) |
unexpected と actual が異なることを検証 |
System.assertNotEquals(unexpected, actual, message) |
unexpected と actual が等しい場合、message を表示 |
1.2 アサーションの実際の使用例
✅ System.assert() の例
@isTest
private class AssertExampleTest {
@isTest
static void testAssert() {
Boolean isActive = true;
System.assert(isActive, 'isActive should be true');
}
}
ポイント:
isActiveがtrueであることを検証します。falseの場合、テストは失敗し、エラーメッセージが表示されます。
✅ System.assertEquals() の例
@isTest
private class AssertExampleTest {
@isTest
static void testAssertEquals() {
Integer expected = 100;
Integer actual = 50 + 50;
System.assertEquals(expected, actual, 'Sum calculation is incorrect');
}
}
ポイント:
actualの値 (50 + 50) がexpected(100) と一致するかを検証します。一致しない場合、エラーメッセージが表示されます。
✅ System.assertNotEquals() の例
@isTest
private class AssertExampleTest {
@isTest
static void testAssertNotEquals() {
String unexpected = 'Hello';
String actual = 'World';
System.assertNotEquals(unexpected, actual, 'Strings should not match');
}
}
ポイント:
actual('World') がunexpected('Hello') と異なることを確認します。
一致していた場合、テストは失敗します。
2. System.runAs() を用いたセキュリティテスト
2.1 System.runAs() とは?
System.runAs() を使うと、別のユーザーの権限で Apex コードを実行 できます。
これにより、特定の プロファイルや権限セットのユーザーが操作できるか をテストできます。
2.2 System.runAs() の基本的な使い方
@isTest
private class RunAsExampleTest {
@isTest
static void testRunAs() {
// テストユーザーの作成
User testUser = new User(
LastName = 'Test User',
Email = 'testuser@example.com',
Username = 'testuser@example.com' + System.currentTimeMillis(),
Alias = 'tuser',
ProfileId = [SELECT Id FROM Profile WHERE Name = 'Standard User' LIMIT 1].Id,
TimeZoneSidKey = 'America/Los_Angeles',
LocaleSidKey = 'en_US',
EmailEncodingKey = 'UTF-8',
LanguageLocaleKey = 'en_US'
);
insert testUser;
// testUser の権限で処理を実行
System.runAs(testUser) {
System.assertEquals(UserInfo.getUserId(), testUser.Id, 'User should be testUser');
}
}
}
ポイント:
System.runAs(testUser)の中ではtestUserの権限で処理が実行されるUserInfo.getUserId()を使って現在のユーザーがtestUserであることを確認
2.3 System.runAs() による混合 DML エラーの回避
混合 DML エラーとは?
Apex では 標準オブジェクト(User など)とカスタムオブジェクトを同じトランザクションで操作するとエラー になります。
@isTest
private class MixedDMLErrorExample {
@isTest
static void testMixedDML() {
// ユーザーを作成(標準オブジェクト)
User testUser = new User(
LastName = 'Test User',
Email = 'testuser@example.com',
Username = 'testuser@example.com' + System.currentTimeMillis(),
Alias = 'tuser',
ProfileId = [SELECT Id FROM Profile WHERE Name = 'Standard User' LIMIT 1].Id,
TimeZoneSidKey = 'America/Los_Angeles',
LocaleSidKey = 'en_US',
EmailEncodingKey = 'UTF-8',
LanguageLocaleKey = 'en_US'
);
// カスタムオブジェクトのレコードを作成
Pokemon__c p = new Pokemon__c(Name='Pikachu', Type__c='Electric');
try {
insert testUser;
insert p; // ここでエラー(Mixed DML error)
} catch (Exception e) {
System.debug('混合 DML エラー: ' + e.getMessage());
}
}
}
このコードはエラーになります(標準オブジェクト
UserとPokemon__cを同じトランザクションで処理)
解決策: System.runAs() を使う
@isTest
private class MixedDMLFixExample {
@isTest
static void testMixedDMLFixed() {
// ユーザーを作成
User testUser = new User(
LastName = 'Test User',
Email = 'testuser@example.com',
Username = 'testuser@example.com' + System.currentTimeMillis(),
Alias = 'tuser',
ProfileId = [SELECT Id FROM Profile WHERE Name = 'Standard User' LIMIT 1].Id,
TimeZoneSidKey = 'America/Los_Angeles',
LocaleSidKey = 'en_US',
EmailEncodingKey = 'UTF-8',
LanguageLocaleKey = 'en_US'
);
insert testUser;
// System.runAs() で混合 DML を回避
System.runAs(testUser) {
Pokemon__c p = new Pokemon__c(Name='Pikachu', Type__c='Electric');
insert p; // User の作成とは別トランザクションになるためエラー回避
}
}
}
ポイント:
System.runAs()を使うと 標準オブジェクトとカスタムオブジェクトの DML を別トランザクションで処理 できる- これにより 混合 DML エラーを回避 できる
まとめ
✅ System.assert() を使ってテストの期待値を検証
✅ System.runAs() を使って権限別の動作をテスト
✅ System.runAs() を活用して 混合 DML エラー を回避
これらの方法を活用すれば、テストの品質を向上させ、エラーを未然に防ぐことが可能 です!🚀