创建一个可单元测试的 API 客户端
Creating an API client that's unit testable
我目前正在构建一个简单的 API 客户端,它将为远程服务的 HTTP API 提供一个很好的包装器。我无法弄清楚如何在我的客户端中模拟 HTTP 响应,以使其易于测试。
举个例子class:
<?php
class ApiClient
{
const API_BASEURL = 'https://api.someservice.com/v1';
protected $applicationId;
protected $secretKey;
public function __construct($applicationId, $secretKey)
{
$this->applicationId = $applicationId;
$this->secretKey = $secretKey;
}
public function listAccounts()
{
$response = \Httpful\Request::get(self::API_BASEURL.'/accounts')
->expectsJson()
->send();
return $response->accounts;
}
}
我希望使用我的客户端的开发人员能够像这样使用它:
$client = new ApiClient($applicationId, $secretKey);
$accounts = $client->listAccounts();
实际上,这工作得很好。但是我真的很难对 listAccounts()
方法进行单元测试,因为它将 HTTP 请求发送到硬编码的 API_BASEURL
。显然,我不希望我的测试实际触发对远程服务的网络调用。
我想解决这个问题的一种方法是模拟 \Httpful\Request
class,使其成为 return 一个 "faked" 响应而不是实际访问网络。但是如何将模拟的 class 传递到我的 listAccounts()
方法中呢?为了测试,我无法将其签名更改为 listAccounts($mockedRequest = null)
。
我进行测试的最佳方法是什么?
通常,您应该将请求对象注入 class(通过构造函数参数传递)并移除硬依赖。但是在您的情况下,没有可以用模拟替换的请求对象。 这就是静态方法的问题。如果你想编写单元测试,这个 Httpful 库似乎不是一个好的选择。
我看到两个选项:
- 使用不同的、更多的 test-friendly 库,例如 Guzzle
如果那不可能,写一个薄的包装器,像这样:
class HttpfulClient
{
public function createGetRequest($url)
{
return \Httpful\Request::get($url);
}
}
然后将其实例传递给 ApiClient 构造函数并在您的测试中对其进行模拟。
我目前正在构建一个简单的 API 客户端,它将为远程服务的 HTTP API 提供一个很好的包装器。我无法弄清楚如何在我的客户端中模拟 HTTP 响应,以使其易于测试。
举个例子class:
<?php
class ApiClient
{
const API_BASEURL = 'https://api.someservice.com/v1';
protected $applicationId;
protected $secretKey;
public function __construct($applicationId, $secretKey)
{
$this->applicationId = $applicationId;
$this->secretKey = $secretKey;
}
public function listAccounts()
{
$response = \Httpful\Request::get(self::API_BASEURL.'/accounts')
->expectsJson()
->send();
return $response->accounts;
}
}
我希望使用我的客户端的开发人员能够像这样使用它:
$client = new ApiClient($applicationId, $secretKey);
$accounts = $client->listAccounts();
实际上,这工作得很好。但是我真的很难对 listAccounts()
方法进行单元测试,因为它将 HTTP 请求发送到硬编码的 API_BASEURL
。显然,我不希望我的测试实际触发对远程服务的网络调用。
我想解决这个问题的一种方法是模拟 \Httpful\Request
class,使其成为 return 一个 "faked" 响应而不是实际访问网络。但是如何将模拟的 class 传递到我的 listAccounts()
方法中呢?为了测试,我无法将其签名更改为 listAccounts($mockedRequest = null)
。
我进行测试的最佳方法是什么?
通常,您应该将请求对象注入 class(通过构造函数参数传递)并移除硬依赖。但是在您的情况下,没有可以用模拟替换的请求对象。 这就是静态方法的问题。如果你想编写单元测试,这个 Httpful 库似乎不是一个好的选择。
我看到两个选项:
- 使用不同的、更多的 test-friendly 库,例如 Guzzle
如果那不可能,写一个薄的包装器,像这样:
class HttpfulClient { public function createGetRequest($url) { return \Httpful\Request::get($url); } }
然后将其实例传递给 ApiClient 构造函数并在您的测试中对其进行模拟。