Hed*_*dam 5 php unit-testing laravel stripe-payments
我正在 Laravel 中创建一个基于订阅的 SaaS 平台,其中 Laravel Cashier 不适合我的需求。因此,我需要使用 Stripe 库自己实现订阅引擎。
我发现通过挂钩一个Subscription
类的创建和删除事件,然后相应地创建或取消一个 Stripe 订阅,很容易实现 Laravel 和 Stripe 之间的连接。
不幸的是,Stripe 库主要基于对某些预定义类(.. like \Stripe\Charge::create()
)调用静态方法。
这让我很难测试,因为您通常会允许依赖注入某些自定义客户端进行模拟,但是由于 Stripe 库是静态引用的,因此没有要注入的客户端。有什么方法可以创建 Stripe 客户端类等,我可以模拟吗?
小智 5
你好,来自未来!
我只是在研究这个。所有这些类都从 Stripe 的ApiResource
类扩展而来,继续挖掘,您会发现当库要发出 HTTP 请求时,它会调用$this->httpClient()
. 该httpClient
方法返回对名为 的变量的静态引用$_httpClient
。方便的是,Stripe 类上还有一个ApiRequestor
名为 的静态方法,它接受一个应该实现 Stripe 的setHttpClient
对象(该接口仅描述一个名为 的方法)。HttpClient\ClientInterface
request
Soooooo,在您的测试中,您可以调用ApiRequestor::setHttpClient
它来传递您自己的 http 客户端模拟的实例。然后,每当 Stripe 发出 HTTP 请求时,它都会使用您的模拟而不是默认的CurlClient
。然后,您的责任是让您的模拟返回格式良好的 Stripe 式响应,并且您的应用程序将不会变得更明智。
这是我在测试中开始使用的一个非常愚蠢的假货:
<?php
namespace Tests\Doubles;
use Stripe\HttpClient\ClientInterface;
class StripeHttpClientFake implements ClientInterface
{
private $response;
private $responseCode;
private $headers;
public function __construct($response, $code = 200, $headers = [])
{
$this->setResponse($response);
$this->setResponseCode($code);
$this->setHeaders($headers);
}
/**
* @param string $method The HTTP method being used
* @param string $absUrl The URL being requested, including domain and protocol
* @param array $headers Headers to be used in the request (full strings, not KV pairs)
* @param array $params KV pairs for parameters. Can be nested for arrays and hashes
* @param boolean $hasFile Whether or not $params references a file (via an @ prefix or
* CURLFile)
*
* @return array An array whose first element is raw request body, second
* element is HTTP status code and third array of HTTP headers.
* @throws \Stripe\Exception\UnexpectedValueException
* @throws \Stripe\Exception\ApiConnectionException
*/
public function request($method, $absUrl, $headers, $params, $hasFile)
{
return [$this->response, $this->responseCode, $this->headers];
}
public function setResponseCode($code)
{
$this->responseCode = $code;
return $this;
}
public function setHeaders($headers)
{
$this->headers = $headers;
return $this;
}
public function setResponse($response)
{
$this->response = file_get_contents(base_path("tests/fixtures/stripe/{$response}.json"));
return $this;
}
}
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助 :)