You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

如何在PHPUnit中Mock Guzzle请求并测试CategoryClient类

在PHPUnit中Mock CategoryClient的JSON响应并设置$this->categories变量

我有这么一个CategoryClient类,它在构造函数里通过Guzzle的Client请求远程接口获取JSON数据,然后转成Collection赋值给私有属性$categories

class CategoryClient { 
    private $categories; 
    /** 
     * Constructor 
     * Retrieves JSON File 
     */ 
    public function __construct(Client $client) { 
        $response = $client->request('GET', config('services.url')); 
        $this->categories = collect(json_decode($response->getBody(), true)); 
    } 
}

现在想在PHPUnit测试里Mock这个JSON响应,并且能验证$this->categories被正确设置,该怎么做呢?


别担心,咱们可以通过Mock Guzzle的ClientResponse对象来实现,步骤很清晰:

1. Mock Guzzle的Client实例

我们需要让Mock的Client在调用request方法时,返回我们预设的响应对象,而不是真的发HTTP请求。

2. 创建Mock的Response对象

用这个Mock响应来模拟接口返回的JSON数据,这样json_decode就能得到我们想要的数组。

3. 实例化CategoryClient并验证结果

因为$categories是私有属性,我们可以用PHPUnit的反射机制来获取它的值;如果允许修改原类,也可以加个公共getter方法,代码会更简洁。

下面是完整的测试代码示例:

use PHPUnit\Framework\TestCase;
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Response;
use App\CategoryClient; // 替换成你的实际命名空间

class CategoryClientTest extends TestCase
{
    public function testCategoriesAreSetFromMockedJsonResponse()
    {
        // 1. 准备我们要模拟的JSON数据
        $mockJsonData = [
            ['id' => 1, 'name' => 'Category 1'],
            ['id' => 2, 'name' => 'Category 2'],
        ];
        $mockJsonString = json_encode($mockJsonData);

        // 2. 创建Mock的Response对象,返回预设的JSON字符串
        $mockResponse = new Response(200, [], $mockJsonString);

        // 3. Mock Guzzle Client,让它的request方法返回我们的Mock响应
        $mockClient = $this->createMock(Client::class);
        $mockClient->method('request')
            ->with('GET', config('services.url')) // 验证请求方法和URL是否正确
            ->willReturn($mockResponse);

        // 4. 实例化CategoryClient
        $categoryClient = new CategoryClient($mockClient);

        // 5. 验证$categories是否被正确设置(用反射获取私有属性)
        $reflection = new \ReflectionClass($categoryClient);
        $categoriesProperty = $reflection->getProperty('categories');
        $categoriesProperty->setAccessible(true);
        $actualCategories = $categoriesProperty->getValue($categoryClient);

        // 断言结果符合预期
        $this->assertEquals(collect($mockJsonData), $actualCategories);
    }
}

补充说明:

  • 如果你的项目基于Laravel,还可以用Http::fake()来更简洁地Mock请求,不过上面的方法是通用的PHPUnit方案,不依赖框架特定工具。
  • 要是允许修改CategoryClient类,建议加一个公共的getCategories()方法,这样就不用反射了:
    public function getCategories()
    {
        return $this->categories;
    }
    
    测试里直接调用$categoryClient->getCategories()来断言即可,代码会更干净直观。

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

火山引擎 最新活动