首页 > 解决方案 > Laravel如何模拟自定义验证规则的SoapClient响应

问题描述

SoapClient拥有一个使用I 现在需要在测试中模拟它的自定义验证规则。

    public function passes( $attribute, $value ): bool
    {
$value = str_replace( [ '.', ' ' ], '', $value );

        $country = strtoupper( substr( $value, 0, 2 ) );
        $vatNumber = substr( $value, 2 );
        $client = new SoapClient('https://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl', [ 'soap_version' => SOAP_1_1 ]);
        $response = $client->checkVat( [ 'countryCode' => $country, 'vatNumber' => $vatNumber ] );

        return $response->valid;
    }

曾经使用laminas-soap包,但不支持 PHP8。使用 laminas-soap 可以做到

$this->mock( Client::class, function( $mock )
{
   $mock->shouldReceive( 'get' )->andReturn( new Response( true, 200 ) );
} );

但这不适用于SoapClient::class.

然后从Phpunit 尝试,模拟 SoapClient 是有问题的(模拟魔术方法)但也失败了:

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

尝试来自本地 XML 的模拟 SoapClient 响应也失败了:

$soapClient->expects($this->once())
        ->method('call')
        ->will(
            $this->returnValue(true)
        );

我的问题是如何模拟使用的自定义验证规则的肥皂响应SoapClient

标签: phplaravelphpunit

解决方案


你可以尝试这样的事情:

//First you need to pass the client in your parameters
public function passes($attribute, $value $client): bool
...

//Then with phpunit it's possible to do 
public function TestPasses() 
{
    //Replace myClasse with your real class wich contain the passes function
    $myClasse = new myClasse();
    
    $clientMock = $this
            ->getMockBuilder(SoapClient::class)
            ->disableOriginalConstructor()
            ->setMethods(['checkVat'])
            ->getMock();
            
    $reponseMock  $this
            ->getMockBuilder(/*Here it should be the classe returned by the checkVat function*/::class)
            ->disableOriginalConstructor()
            ->setMethods(['valid'])
            ->getMock(); 
            
    $clientMock->expects($this->once())
            ->method('checkVat')
            ->with([ 'countryCode' => /*Put the value you want here*/, 'vatNumber' => /*Put the value you want here*/ ])
            ->willReturn($reponseMock);
            
    $reponseMock->expects($this->once())
            ->method('valid')
            ->willReturn(true /*or false if you want*/);
                  
   $result = $myClasse->passes(/*Put the value you want here*/, /*Put the value you want here*/, $clientMock);

   $this->assertEquals(true, $result);
}

推荐阅读