Asynchronous Apex and Mock Callouts

DEX455 - Apex 集成与工具完全指南:Callouts、命名凭据、WSDL2Apex、Mock 测试

📄 第 379 页 🎬 视频课程

课程章节介绍

同学们,咱们今天来看个测试里的小陷阱,就是异步代码和接口调用混在一起的时候,容易出错。 先回忆一下,所谓异步Apex,就是那些不会马上执行完的操作,比如用@future注解的方法、批处理类、定时调度任务。这些异步操作因为不知道什么时候会跑完,所以Salesforce规定:在一个事务里,如果你已经做过DML操作,或者触发过异步调用,就不能再去做外部HTTP的调出了。形象点说,就像你出牌后必须等别人出完,才能再出下一张,不然系统会觉得不安全。 在测试类里,这个规则更严格。有时候我们需要测一个流程:先做异步调用,后面还要测某个callout。直接写的话,一定会出异常,因为测试运行是同步的,异步任务会卡住后面的callout。 那怎么破呢?Salesforce提供了一个专门用于测试的“时间控制”方法:Test.startTest() 和 Test.stopTest()。你可以把它们想象成一个测试专用的小世界。只要你把异步调用放在 startTest 和 stopTest 之间,系统就会“延迟”执行它,直到 stopTest 才真正跑起来。这样一来,在 stopTest 之前你还没真的触发异步,也就不会影响callout的准备;等stopTest执行异步的时候,你可以提前用 mock 把 callout 替换成假数据,完美避开真实调用。 所以,如果你测试代码里既有异步操作,又有外部调用,请记住两个保命方案: - 方案一:直接把异步调用那一整块,用 startTest/stopTest 包起来。这样异步在 stopTest 后才跑,不会挡路。 - 方案二:如果不得已,异步调用必须放在外面,那至少把会发起 callout 的那部分代码,用 startTest/stopTest 包起来,让mock生效的范围覆盖进去。 不这么做的话,测试一跑就会直接给你抛异常,提示“你有未提交的工作,不能做callout”。记住了吗?把异步活动关进 startTest 的小房间里,测试就乖多了。

关键词

Apex Salesforce Developer Guide