You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Salesforce Apex可调用方法测试类报错:列表索引越界,请求协助

问题排查与解决方案

一、「List index out of bounds: 0」错误修复

这个错误核心原因是测试类直接访问了空集合的索引,或是主方法在无匹配数据时返回空列表,导致测试代码报错。常见场景及修复方式:

  • 测试类未判断集合非空:比如直接写results[0]但无匹配Contact时结果为空,需先通过System.assert(!results.isEmpty())判断,或确保测试数据中存在对应Contact。
  • 输入参数未正确构造:测试类未传入有效输入项,主方法直接取request[0].email导致报错,需严格按照Invocable方法要求构造输入列表。

二、实现带命名变量的返回

要返回命名变量,必须定义包装类作为返回类型,而非直接返回List<Id>。以下是修正后的主类示例:

public class ContactLookupByEmail {
    // 输入参数包装类
    public class Request {
        @InvocableVariable(required=true)
        public String email;
    }

    // 带命名变量的返回结果包装类
    public class Result {
        @InvocableVariable(label='Contact ID' description='匹配的Contact记录ID')
        public Id contactId;
        @InvocableVariable(label='Contact姓名' description='匹配的Contact姓名')
        public String contactName;
    }

    @InvocableMethod(label='根据邮箱查询Contact信息' description='传入邮箱地址,返回匹配的Contact记录')
    public static List<Result> getContactIds(List<Request> requests) {
        List<Result> results = new List<Result>();
        Set<String> emails = new Set<String>();

        // 收集非空邮箱并去重
        for(Request req : requests) {
            if(String.isNotBlank(req.email)) {
                emails.add(req.email.toLowerCase());
            }
        }

        // 批量查询Contact,用Map做邮箱映射
        Map<String, Contact> emailContactMap = new Map<String, Contact>();
        for(Contact c : [SELECT Id, Name, Email FROM Contact WHERE Email IN :emails]) {
            emailContactMap.put(c.Email.toLowerCase(), c);
        }

        // 构造返回结果:每个输入对应一个结果,无匹配则返回空字段
        for(Request req : requests) {
            Result res = new Result();
            Contact matchedContact = emailContactMap.get(req.email?.toLowerCase());
            if(matchedContact != null) {
                res.contactId = matchedContact.Id;
                res.contactName = matchedContact.Name;
            }
            results.add(res);
        }
        return results;
    }
}

三、测试类编写与100%覆盖率实现

测试类需覆盖所有分支场景:有匹配Contact、无匹配、空邮箱、多输入,同时避免索引越界问题。示例如下:

@IsTest
private class ContactLookupByEmailTest {
    @IsTest
    static void testGetContactIds_WithMatch() {
        // 插入测试数据
        Contact testContact = new Contact(FirstName='测试', LastName='用户', Email='test@example.com');
        insert testContact;

        // 构造输入
        ContactLookupByEmail.Request req = new ContactLookupByEmail.Request();
        req.email = 'test@example.com';
        List<ContactLookupByEmail.Request> requests = new List<ContactLookupByEmail.Request>{req};

        // 调用方法并断言
        List<ContactLookupByEmail.Result> results = ContactLookupByEmail.getContactIds(requests);
        System.assert(!results.isEmpty());
        System.assertEquals(testContact.Id, results[0].contactId);
        System.assertEquals(testContact.Name, results[0].contactName);
    }

    @IsTest
    static void testGetContactIds_NoMatch() {
        // 构造无匹配的输入
        ContactLookupByEmail.Request req = new ContactLookupByEmail.Request();
        req.email = 'no-match@example.com';
        List<ContactLookupByEmail.Request> requests = new List<ContactLookupByEmail.Request>{req};

        List<ContactLookupByEmail.Result> results = ContactLookupByEmail.getContactIds(requests);
        System.assert(!results.isEmpty());
        System.assertNull(results[0].contactId);
    }

    @IsTest
    static void testGetContactIds_EmptyEmail() {
        // 构造空邮箱输入
        ContactLookupByEmail.Request req = new ContactLookupByEmail.Request();
        req.email = '';
        List<ContactLookupByEmail.Request> requests = new List<ContactLookupByEmail.Request>{req};

        List<ContactLookupByEmail.Result> results = ContactLookupByEmail.getContactIds(requests);
        System.assert(!results.isEmpty());
        System.assertNull(results[0].contactId);
    }

    @IsTest
    static void testGetContactIds_MultipleRequests() {
        // 插入多个测试Contact
        Contact c1 = new Contact(FirstName='甲', LastName='用户', Email='a@test.com');
        Contact c2 = new Contact(FirstName='乙', LastName='用户', Email='b@test.com');
        insert new List<Contact>{c1, c2};

        // 构造多输入
        ContactLookupByEmail.Request req1 = new ContactLookupByEmail.Request();
        req1.email = 'a@test.com';
        ContactLookupByEmail.Request req2 = new ContactLookupByEmail.Request();
        req2.email = 'b@test.com';
        ContactLookupByEmail.Request req3 = new ContactLookupByEmail.Request();
        req3.email = 'c@test.com';
        List<ContactLookupByEmail.Request> requests = new List<ContactLookupByEmail.Request>{req1, req2, req3};

        List<ContactLookupByEmail.Result> results = ContactLookupByEmail.getContactIds(requests);
        System.assertEquals(3, results.size());
        System.assertEquals(c1.Id, results[0].contactId);
        System.assertEquals(c2.Id, results[1].contactId);
        System.assertNull(results[2].contactId);
    }
}

四、关键注意事项

  • 始终返回与输入数量一致的结果:即使无匹配,也要添加空结果对象,避免返回空列表导致Flow或测试报错。
  • 用Set对邮箱去重:减少SOQL查询次数,提升性能。
  • 空值校验:对输入邮箱做非空判断,避免空指针异常。
  • 覆盖所有分支:测试类要覆盖有匹配、无匹配、空输入、多输入等所有逻辑分支,确保100%代码覆盖率。

内容的提问来源于stack exchange,提问作者jlinville

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 22:00:31