Apex中如何为OrderSummary等生成对象编写单元测试?
核心前提
OrderSummary是Salesforce Order Management模块的系统托管对象,默认测试上下文既不支持直接DML插入,也不会自动触发生成,ConnectApi相关操作也要求开启SeeAllData违反测试隔离原则,最优解是通过依赖注入+Mock层绕开真实数据库查询,具体实现方案如下:
方案1:依赖注入+静态Mock实现(最推荐,符合Apex测试最佳实践)
- 第一步:抽离OrderSummary查询逻辑到单独服务类,同时定义对应接口,示例代码:
// 定义服务接口 public interface IOrderSummaryService { List<OrderSummary> getByOrderId(Id orderId); } // 真实业务实现类 public class OrderSummaryServiceImpl implements IOrderSummaryService { public List<OrderSummary> getByOrderId(Id orderId) { return [SELECT Id, OrderId, TotalAmount FROM OrderSummary WHERE OrderId = :orderId]; } }
- 第二步:业务代码依赖接口而非具体实现,通过构造方法/工厂类注入实现类:
public class OrderBusinessService { private IOrderSummaryService summaryService; // 默认用真实实现,测试时可传入mock实现 public OrderBusinessService() { this.summaryService = new OrderSummaryServiceImpl(); } public OrderBusinessService(IOrderSummaryService mockService) { this.summaryService = mockService; } // 你的业务方法,直接调用summaryService的查询方法即可 }
- 第三步:测试时实现自定义Mock类,返回你构造的测试数据,无需访问真实数据库:
// 测试用Mock实现类 @isTest public class MockOrderSummaryService implements IOrderSummaryService { private List<OrderSummary> mockData; public MockOrderSummaryService(List<OrderSummary> mockData) { this.mockData = mockData; } public List<OrderSummary> getByOrderId(Id orderId) { return mockData; } } // 测试用例示例 @isTest private static void testOrderSummaryLogic() { // 构造你需要的假OrderSummary数据 List<OrderSummary> mockSummaries = new List<OrderSummary>(); OrderSummary mockSum = new OrderSummary( OrderId = '00kxxxxxxx', // 替换为你测试用的OrderId TotalAmount = 1000.00 ); mockSummaries.add(mockSum); // 注入mock实现到业务类 OrderBusinessService businessService = new OrderBusinessService(new MockOrderSummaryService(mockSummaries)); // 后续直接调用业务方法测试即可,不需要真实存在OrderSummary数据 }
方案2:使用Apex Stub API动态Mock(无需单独写Mock类)
如果不想额外创建Mock实现类,可以用Salesforce自带的Stub API动态指定方法返回值,适合方法较多的场景,示例代码:
@isTest public class MockProvider implements System.StubProvider { private Map<String, Object> methodReturnMap; public MockProvider(Map<String, Object> returnMap) { this.methodReturnMap = returnMap; } public Object handleMethodCall(Object stubbedObject, String stubbedMethodName, Type returnType, List<Type> listOfParamTypes, List<String> listOfParamNames, List<Object> listOfArgs) { return methodReturnMap.get(stubbedMethodName); } } // 测试用例中使用 @isTest private static void testDynamicMock() { List<OrderSummary> mockSummaries = new List<OrderSummary>{new OrderSummary(TotalAmount = 1000)}; Map<String, Object> returnMap = new Map<String, Object>{'getByOrderId' => mockSummaries}; IOrderSummaryService mockService = (IOrderSummaryService)Test.createStub(IOrderSummaryService.class, new MockProvider(returnMap)); OrderBusinessService businessService = new OrderBusinessService(mockService); // 后续执行业务测试 }
临时应急方案:测试上下文判断返回Mock数据
如果暂时没有时间重构代码抽离服务类,可以在查询逻辑中增加测试上下文判断,直接返回构造的测试数据,该方案侵入性较强,仅建议临时使用:
public List<OrderSummary> getOrderSummaries(Id orderId) { // 测试上下文直接返回mock数据 if(Test.isRunningTest()) { return new List<OrderSummary>{new OrderSummary(OrderId = orderId, TotalAmount = 1000)}; } // 生产环境执行真实查询 return [SELECT Id, TotalAmount FROM OrderSummary WHERE OrderId = :orderId]; }
内容的提问来源于stack exchange,提问作者Jason C
相关产品推荐
相关产品推荐

