【问题标题】:Laravel how to mock SoapClient response for custom validation ruleLaravel如何模拟自定义验证规则的SoapClient响应
【发布时间】:2021-02-12 11:05:13
【问题描述】:

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

    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, mocking SoapClient is problematic (mock magic methods)尝试,但也失败了:

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

mock SoapClient response from local XML 尝试过也失败了:

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

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

【问题讨论】:

    标签: php laravel phpunit


    【解决方案1】:

    你可以试试这样的:

    //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);
    }
    

    【讨论】:

    • passes 方法是验证 Rule 的一部分,它是 Laravel 中 FormRequest 的一部分,因此仅在创建或更新操作时触发。自定义验证规则是从 Laravel 父级 Rule 类扩展而来的,因此 passes 方法被固定在这些参数上。
    【解决方案2】:

    找到了这个laravel soap 包,它提供了一个易于使用的Soap::fake

    如:

    Soap::fake(function ($request) {
        return Soap::response('Hello World', 200);
    });
    

    【讨论】:

      猜你喜欢
      • 2020-05-08
      • 2017-04-11
      • 2018-02-18
      • 2017-12-01
      • 2019-02-12
      • 2016-11-22
      • 2019-12-14
      • 2018-05-25
      • 2016-11-14
      相关资源
      最近更新 更多