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
相关产品推荐
相关产品推荐

