0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ApexのテストにおけるアサーションとSystem.runAs()の活用

Posted at

Salesforce Apex のテストにおけるアサーションと System.runAs() の活用

Apex のテストでは、アサーション (Assertion) を使用して実行結果を検証 します。また、System.runAs() を使ったセキュリティテスト や、混合 DML エラーの回避 についても解説します。


1. アサーションを使用した実行結果の検証

アサーションとは?

アサーションは、テストの期待値と実際の結果を比較して、正しく動作しているかを確認する ためのものです。Apex では System クラスのメソッドを使ってアサーションを行います。


1.1 System クラスのアサーション一覧

メソッド 説明
System.assert(condition) conditiontrue であることを検証
System.assert(condition, message) conditiontrue でない場合、message を表示
System.assertEquals(expected, actual) expectedactual が等しいことを検証
System.assertEquals(expected, actual, message) expectedactual が等しくない場合、message を表示
System.assertNotEquals(unexpected, actual) unexpectedactual が異なることを検証
System.assertNotEquals(unexpected, actual, message) unexpectedactual が等しい場合、message を表示

1.2 アサーションの実際の使用例

System.assert() の例

@isTest
private class AssertExampleTest {
    @isTest
    static void testAssert() {
        Boolean isActive = true;
        System.assert(isActive, 'isActive should be true');
    }
}

ポイント:
isActivetrue であることを検証します。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());
        }
    }
}

このコードはエラーになります(標準オブジェクト UserPokemon__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 エラー を回避

これらの方法を活用すれば、テストの品質を向上させ、エラーを未然に防ぐことが可能 です!🚀

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?