You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何编写PHPUnit测试验证testLink方法中authorize的调用逻辑

如何为testLink方法编写单元测试验证authorize调用逻辑

我们有一个testLink方法,其内部会在两种场景下调用$this->authorize()方法,需要编写单元测试来验证这部分业务逻辑。

目标方法代码

public function testLink($itemId): bool
{
    $token = $this->settingRepository->getValue(self::SETTING_ADMITAD_TOKEN);
    if ($token) {
        $this->token = $token;
    }

    if (!$this->token) {
        $this->authorize();
    }

    // 注:原代码中$response变量未显式初始化,推测此处应有$response = $this->validateLinkRequest($itemId);
    if ($response->getStatusCode() === 401) {
        $this->statusCode = 401;
        $this->authorize();

        $response = $this->validateLinkRequest($itemId);
    }

    if ($response->getStatusCode() === 200 && json_decode($response->getContent())->message === self::ADMITAD_SUCCESS_RESPONSE) {
        return true;
    } else {
        return false;
    }
}

项目已有单元测试示例

public function testAuthorize()
{
    $mockHttpClient = new MockHttpClient(
        [
            new MockResponse(
                json_encode([
                    "error_description" => "Token is expired",
                    "status_code" => 401,
                    "error_code" => 0,
                    "error" => "invalid_token"
                ]),
                [
                    'response_headers' => [
                        'content-type' => 'application/json',
                    ],
                    'http_code' => 401,
                ]
            ),
        ]
    );
    self::$container->set(HttpClientInterface::class, $mockHttpClient);
    $provider = self::$container->get(AdmitadDataProvider::class);
    $response = $provider->validateLinkRequest(self::ITEM_ID_1);
    $this->expectException(ClientException::class);
    $this->expectExceptionCode(401);
}

单元测试编写指导

我们需要针对authorize()的三种调用场景分别编写测试:

场景1:无配置token,首次请求成功(非401)

此时testLink会因$this->token不存在调用一次authorize(),后续请求成功无需再次调用。

public function testTestLinkCallsAuthorizeOnceWhenNoTokenAndRequestSucceeds()
{
    // 1. Mock SettingRepository,返回空token
    $mockSettingRepo = $this->createMock(SettingRepository::class);
    $mockSettingRepo->method('getValue')
        ->with(self::SETTING_ADMITAD_TOKEN)
        ->willReturn(null);

    // 2. Mock validateLinkRequest返回200成功响应
    $mockSuccessResponse = new MockResponse(
        json_encode(['message' => self::ADMITAD_SUCCESS_RESPONSE]),
        ['http_code' => 200, 'response_headers' => ['content-type' => 'application/json']]
    );
    $mockHttpClient = new MockHttpClient([$mockSuccessResponse]);
    self::$container->set(HttpClientInterface::class, $mockHttpClient);

    // 3. 创建被测对象,替换依赖并mock authorize方法
    $mockProvider = $this->getMockBuilder(AdmitadDataProvider::class)
        ->setConstructorArgs([self::$container])
        ->onlyMethods(['authorize'])
        ->getMock();

    $mockProvider->settingRepository = $mockSettingRepo;
    $mockProvider->expects($this->once())
        ->method('authorize');

    // 4. 执行测试方法
    $result = $mockProvider->testLink(self::ITEM_ID_1);
    $this->assertTrue($result);
}

场景2:有配置token,但首次请求返回401

此时$this->token存在,不会触发首次authorize();但因请求返回401,会调用一次authorize(),重新请求后成功。

public function testTestLinkCallsAuthorizeOnceWhenTokenExistsButFirstRequestFails()
{
    // 1. Mock SettingRepository返回有效token
    $mockSettingRepo = $this->createMock(SettingRepository::class);
    $mockSettingRepo->method('getValue')
        ->with(self::SETTING_ADMITAD_TOKEN)
        ->willReturn('valid_token');

    // 2. Mock HttpClient先返回401,再返回200成功响应
    $mockResponses = [
        new MockResponse(
            json_encode(['error' => 'invalid_token']),
            ['http_code' => 401, 'response_headers' => ['content-type' => 'application/json']]
        ),
        new MockResponse(
            json_encode(['message' => self::ADMITAD_SUCCESS_RESPONSE]),
            ['http_code' => 200, 'response_headers' => ['content-type' => 'application/json']]
        )
    ];
    $mockHttpClient = new MockHttpClient($mockResponses);
    self::$container->set(HttpClientInterface::class, $mockHttpClient);

    // 3. 创建被测对象并mock authorize方法
    $mockProvider = $this->getMockBuilder(AdmitadDataProvider::class)
        ->setConstructorArgs([self::$container])
        ->onlyMethods(['authorize'])
        ->getMock();

    $mockProvider->settingRepository = $mockSettingRepo;
    $mockProvider->expects($this->once())
        ->method('authorize');

    // 4. 执行测试
    $result = $mockProvider->testLink(self::ITEM_ID_1);
    $this->assertTrue($result);
}

场景3:无配置token,首次请求返回401

此时会先因无token调用一次authorize(),再因请求401调用第二次authorize(),最终请求成功。

public function testTestLinkCallsAuthorizeTwiceWhenNoTokenAndFirstRequestFails()
{
    // 1. Mock SettingRepository返回空token
    $mockSettingRepo = $this->createMock(SettingRepository::class);
    $mockSettingRepo->method('getValue')
        ->with(self::SETTING_ADMITAD_TOKEN)
        ->willReturn(null);

    // 2. Mock HttpClient先返回401,再返回200成功响应
    $mockResponses = [
        new MockResponse(
            json_encode(['error' => 'invalid_token']),
            ['http_code' => 401, 'response_headers' => ['content-type' => 'application/json']]
        ),
        new MockResponse(
            json_encode(['message' => self::ADMITAD_SUCCESS_RESPONSE]),
            ['http_code' => 200, 'response_headers' => ['content-type' => 'application/json']]
        )
    ];
    $mockHttpClient = new MockHttpClient($mockResponses);
    self::$container->set(HttpClientInterface::class, $mockHttpClient);

    // 3. 创建被测对象并mock authorize方法
    $mockProvider = $this->getMockBuilder(AdmitadDataProvider::class)
        ->setConstructorArgs([self::$container])
        ->onlyMethods(['authorize'])
        ->getMock();

    $mockProvider->settingRepository = $mockSettingRepo;
    $mockProvider->expects($this->exactly(2))
        ->method('authorize');

    // 4. 执行测试
    $result = $mockProvider->testLink(self::ITEM_ID_1);
    $this->assertTrue($result);
}

关键注意事项

  • 使用PHPUnit的getMockBuilder来mockauthorize()方法,通过expects()断言调用次数是否符合预期
  • 针对不同场景MockSettingRepository的返回值,控制是否触发首次authorize()
  • 用MockHttpClient模拟validateLinkRequest的不同响应,控制是否触发第二次authorize()
  • 原代码中$response变量未显式初始化,需补充$response = $this->validateLinkRequest($itemId);逻辑,否则测试会报错

内容的提问来源于stack exchange,提问作者Ilya Mironchikov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 21:12:52