在 Salesforce Apex 的测试类中,当需要模拟多个不同的 HTTP 响应时,可以使用 HttpCalloutMock
接口并实现逻辑来区分不同的 HTTP 请求并返回不同的响应。
如果多个 HTTP 请求都使用同一个 HttpCalloutMock
实例,而没有区分逻辑,则只会返回一个默认的响应,这可能会导致测试结果不符合预期。
解决方法:自定义 Mock 逻辑
通过实现自定义的 HttpCalloutMock
,根据请求的 URL 或其他信息区分不同的 HTTP 请求,返回相应的响应。
以下是一个示例代码:
@isTest
public class MultiHttpMockTest {// 自定义 HttpMock 类public class CustomHttpCalloutMock implements HttpCalloutMock {public HTTPResponse respond(HTTPRequest req) {HttpResponse res = new HttpResponse();// 根据请求的 URL 或 Body 区分不同的响应if (req.getEndpoint().contains('https://example.com/api1')) {res.setStatusCode(200);res.setBody('{"result": "Response for API 1"}');} else if (req.getEndpoint().contains('https://example.com/api2')) {res.setStatusCode(200);res.setBody('{"result": "Response for API 2"}');} else {res.setStatusCode(404);res.setBody('{"error": "Not Found"}');}return res;}}@isTeststatic void testMultipleCallouts() {// 设置自定义 HttpMockTest.setMock(HttpCalloutMock.class, new CustomHttpCalloutMock());// 模拟第一个 API 调用HttpRequest req1 = new HttpRequest();req1.setEndpoint('https://example.com/api1');req1.setMethod('GET');HttpResponse res1 = new Http().send(req1);System.assertEquals(200, res1.getStatusCode());System.assert(res1.getBody().contains('Response for API 1'));// 模拟第二个 API 调用HttpRequest req2 = new HttpRequest();req2.setEndpoint('https://example.com/api2');req2.setMethod('GET');HttpResponse res2 = new Http().send(req2);System.assertEquals(200, res2.getStatusCode());System.assert(res2.getBody().contains('Response for API 2'));}
}
核心思路
- 自定义
HttpCalloutMock
:实现HttpCalloutMock
接口,在respond
方法中根据请求的内容返回不同的响应。 - 使用区分条件:通过
req.getEndpoint()
、req.getBody()
或其他属性区分请求。 - 设置 Mock:使用
Test.setMock()
方法设置自定义的HttpCalloutMock
。 - 在测试中验证:通过
HttpResponse
验证每次 HTTP 调用返回的内容是否符合预期。
注意事项
- 确保请求的区分逻辑准确:避免因为相似的条件导致错误的响应。
- 覆盖所有测试场景:为每种可能的请求配置对应的响应,确保测试的完整性。
- 验证 HTTP 响应内容:不仅要验证状态码,还要验证响应的主体是否符合预期。
这种方式可以确保在测试类中正确模拟多个 HTTP 请求和响应。