如何测试与第三方 API 交互的服务?

我有以下服务要测试:


namespace App\Service;


class ApiManager

{

   public function getProjects()

   {

      $projects = $this->pager->fetchAll(

                $this->client->api('projects'),

                'all',

                [['simple' => true]]

      );

   }

}

该服务使用用于 PHP 的 Gitlab API 捆绑包。因此,$projects中的数据如下所示:


[

   0 => [

           'id' => 1,

           'title' => 'Project #1',

           'description' => 'Project description...'

        ],

   1 => [

           'id' => 2,

           'title' => 'Project #2',

           'description' => 'Project description...'

        ],

]

当然,我不想用来自API的真实数据进行测试。如何模拟从 getProjects 中的 HTTP 请求返回的数据?


慕田峪9158850
浏览 155回答 3
3回答

慕姐4208626

将 外部化到您自己的服务中,例如 ProjectService,并将其注入到 ApiManager 中。public function getProjects()创建两个版本的 ProjectService:ProjectService 和 ProjectMockService,首先当然用于生产,2nd 应该返回模拟值(无论你在这里需要什么)。然后为生产和测试环境维护 services.yaml。根据活动环境的不同,将注入正确版本的 ProjectService。

POPMUISE

理想情况下,您的应用程序应将来自第三方 API 的数据转换为包含在您自己的应用程序中的模型。然后,应用程序应仅使用此模型的实例,而不是从 API 返回的数据。这种抽象级别使测试更容易,因为只有一个地方使用API数据:在某种映射中。服务类可以从 API 获取数据,然后映射器将响应转换为域对象。为了回答你的实际问题,我不会真正测试对API的HTTP调用。测试网络调用会使测试套件变慢,并且在没有网络连接的环境中会失败。相反,我会使用 API 中预先保存的或虚拟响应来测试映射器。如果 API 在某个时候开始以不同的“形状”返回数据,则代码中只有一个位置需要更改(映射层)。

慕的地10843

在这种特定情况下,您不需要任何花哨的东西。您已经拥有依赖项(我希望您通过以下方式接收)。如果是这种情况,请继续模拟单元测试您的方法。Pager__construct()$this->pager->fetchAll()如下所示:ApiManagerTest.phpclass ApiManagerTest extends TestCase{    private $pager;    private $apiManager;    public function setUp(): void    {        $this->pager = $this->prophesize(Pager::class);        // Notice we pass the mocked `pager` object here        $this->apiManager = new ApiManager(            $this->pager->reveal()        );    }    public function testGetProjects(): void    {        // Given        $projects = $this->givenTwoProjectsExist();        $this->pager->getProjects(            'projects',            'all',            [['simple' => true]]        )        ->shouldBeCalledOnce()        ->willReturn($projects);        // When        $result = $this->apiManager->fetchAll();        // Then        self::assertEquals($projects, $result);    }}您可以在此处阅读有关“给定,何时,然后”结构的更多信息:https://thephp.website/en/issue/clean-tests-with-php-and-phpunit/
打开App,查看更多内容
随时随地看视频慕课网APP