如何在Laravel测试用例中伪造/模拟DocuSign API
如何在不调用真实DocuSign API的情况下编写测试用例
核心思路是利用PHPUnit的Mock功能伪造DocuSign SDK中的TemplatesApi类,模拟它的行为,避免发起真实API请求。以下是具体实现步骤:
1. 调整业务代码,支持依赖注入
先修改你的业务类,将TemplatesApi的实例化改为构造函数注入,而非在方法内直接new,这样测试时可以替换为Mock对象:
class ContractTemplateService { private $templatesApi; private $accountId; public function __construct(TemplatesApi $templatesApi, string $accountId) { $this->templatesApi = $templatesApi; $this->accountId = $accountId; } public function validateContractTemplateId(string $contractTemplateId): bool { try { $this->templatesApi->get($this->accountId, $contractTemplateId); } catch (ApiException $e) { $errorMessage = $e->getResponseBody(); throw new CustomApiException($errorMessage, $errorMessage->message, $e->getCode()); } return true; } }
2. 编写测试用例(成功场景)
模拟TemplatesApi::get方法正常执行的情况,验证接口返回200:
public function test_contract_template_update_with_valid_id() { // 创建TemplatesApi的Mock对象 $templatesApiMock = $this->createMock(TemplatesApi::class); // 模拟get方法:不抛出异常,模拟API调用成功 $templatesApiMock->method('get') ->with($this->equalTo('your-test-account-id'), $this->anything()) ->willReturn(null); // 注入Mock服务到容器 $contractService = new ContractTemplateService($templatesApiMock, 'your-test-account-id'); $this->app->instance(ContractTemplateService::class, $contractService); // 执行测试请求 $dataSet = [ 'dealer_id' => $this->user->id, 'contract_template_id' => faker()->uuid(), ]; $this->actingAs($this->user) ->put( route('sdu.dealers.contract-template.update', ['dealer' => $this->dealer->id]), $dataSet ) ->assertStatus(Response::HTTP_OK); }
3. 编写测试用例(失败场景)
模拟TemplatesApi::get抛出异常的情况,验证接口返回对应错误状态:
public function test_contract_template_update_with_invalid_id() { // 创建ApiException的Mock,模拟错误响应 $apiExceptionMock = $this->createMock(ApiException::class); $errorResponse = (object) ['message' => 'Template not found']; $apiExceptionMock->method('getResponseBody')->willReturn($errorResponse); $apiExceptionMock->method('getCode')->willReturn(404); // 创建TemplatesApi的Mock,让get方法抛出异常 $templatesApiMock = $this->createMock(TemplatesApi::class); $templatesApiMock->method('get') ->with($this->equalTo('your-test-account-id'), $this->anything()) ->willThrowException($apiExceptionMock); // 注入Mock服务 $contractService = new ContractTemplateService($templatesApiMock, 'your-test-account-id'); $this->app->instance(ContractTemplateService::class, $contractService); // 执行测试并断言错误结果 $dataSet = [ 'dealer_id' => $this->user->id, 'contract_template_id' => 'invalid-template-id', ]; $this->actingAs($this->user) ->put( route('sdu.dealers.contract-template.update', ['dealer' => $this->dealer->id]), $dataSet ) ->assertStatus(Response::HTTP_UNPROCESSABLE_ENTITY) ->assertJson(['message' => 'Template not found']); }
补充说明
- 如果使用Laravel,也可以用Mockery替代PHPUnit原生Mock,语法更灵活
- 必须保证依赖的外部服务通过构造函数注入,才能在测试中替换为Mock对象
- 模拟方法时,要根据业务场景设置返回值或异常,覆盖所有测试分支
内容的提问来源于stack exchange,提问作者sssurii
相关产品推荐
相关产品推荐

