在 phpunit 中测试构造函数参数

koj*_*iro 5 php phpunit mocking magento

我们用来Varien_Http_Client从 Magento 扩展发出 http 请求,如下所示:

public function callApi(…)
{
    <SNIP>

    // Set default factory adapter to socket in case curl isn't installed.
    $client = new Varien_Http_Client($apiUri, array(
        'adapter' => 'Zend_Http_Client_Adapter_Socket',
        'timeout' => $timeout, 
    ));
    $client->setRawData($xmlDoc->saveXML())->setEncType('text/xml');
    $response = $client->request($method);
    $results = '';
    if ($response->isSuccessful()) {
        $results = $response->getBody();
    }
    return $results;
}
Run Code Online (Sandbox Code Playgroud)

我知道我应该避免测试Varien_Http_Client;的内部结构。相反,我应该测试我们是否向它发送了正确的输入,并正确处理了它的输出。我可以Varien_Http_Client很容易地模拟,但即使我重构这段代码让我Varien_Http_Client用它的模拟替换,我也不明白如何一般*测试构造函数是用预期的参数调用的,因为构造函数是由PHPUnit::getMock.

我不需要模拟对象;我需要一个模拟。如何测试构造函数是否使用预期参数调用?

*(在这种情况下,我知道解决特定于 的这个问题的方法Varien_Http_Client,但是我可以用更不透明的第三方代码做什么?)

Cyp*_*ian 4

这就是我们所说的“不可测试”的代码。当您在方法中构建依赖项时,无法模拟它们。在模型中每次使用“new”关键字都是一个信号,表明您应该考虑注入对象而不是在内部创建对象。在我看来,该规则的唯一例外是当您创建“数据容器”对象或工厂类时。但在这些情况下,您可能可以测试该对象,因为方法将返回它。

所以正如你所说,你展示的方法需要一些重构,例如:

class ApiClass
{
    protected $client;

    public function __construct(Varien_Http_Client $client)
    {
        $this->client = $client;
    }

    public function callApi()
    {
        $this->client->setRawData($xmlDoc->saveXML())->setEncType('text/xml');

        (...)
Run Code Online (Sandbox Code Playgroud)

最好的!

  • 谢谢!但我还没有走出困境。我必须在*某处*实例化“Varien_Http_Client”,无论发生在哪里,我都可能想要测试,对吧?我该如何避免再次出现这种情况? (2认同)