Phpunit,嘲笑SoapClient是有问题的(模拟魔术方法)

时间:2014-08-14 07:14:11

标签: php web-services soap wsdl phpunit

我试图使用以下代码模拟SoapClient:

$soapClientMock = $this->getMockBuilder('SoapClient')
                ->disableOriginalConstructor()
                ->getMock();
$soapClientMock->method('getAuthenticateServiceSettings')
        ->willReturn(true);

这不起作用,因为Phpunit mockbuilder没有找到函数getAuthenticateServiceSettings。这是WSDL中指定的Soap函数。

但是,如果我扩展了SoapClient类和getAuthenticateServiceSettings方法,它确实有效。

问题是我有100多个SOAP调用,都有自己的参数等等所以我不想模拟每个SOAP函数,或多或少地重新创建整个WSDL文件......

有没有办法模仿"魔法"方法

3 个答案:

答案 0 :(得分:18)

PHPUnit允许您根据wsdl文件存根Web服务。

$soapClientMock = $this->getMockFromWsdl('soapApiDescription.wsdl');
$soapClientMock
    ->method('getAuthenticateServiceSettings')
    ->willReturn(true);

参见此处的示例:

https://phpunit.de/manual/current/en/test-doubles.html#test-doubles.stubbing-and-mocking-web-services.examples.GoogleTest.php

答案 1 :(得分:5)

我通常不直接使用\ SoapClient类,而是使用使用SoapClient的Client类。例如:

class Client
{
    /**
     * @var SoapClient 
     */
    protected $soapClient;

    public function __construct(SoapClient $soapClient)
    {
        $this->soapClient = $soapClient;
    }

    public function getAuthenticateServiceSettings()
    {
        return $this->soapClient->getAuthenticateServiceSettings();
    }
}

这种方式比模拟SoapClient更容易模拟Client类。

答案 2 :(得分:1)

我无法将getMockFromWsdl用于测试场景,因此我嘲笑了在后台调用的__call方法:

    $soapClient = $this->getMockBuilder(SoapClient::class)
        ->disableOriginalConstructor()
        ->getMock();
    $soapClient->expects($this->any())
        ->method('__call')
        ->willReturnCallback(function ($methodName) {
            if ('methodFoo' === $methodName) {
                return 'Foo';
            }
            if ('methodBar' === $methodName) {
                return 'Bar';
            }
            return null;
        });

P.S。我首先尝试使用__soapCall,因为__call已弃用但不起作用。