Laravel 如何为自定义验证规则模拟 SoapClient 响应
Laravel how to mock SoapClient response for custom validation rule
有一个使用 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
的自定义验证规则模拟 soap 响应?
您可以尝试这样的操作:
//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);
}
找到这个 laravel soap 包,它提供了一个易于使用的 Soap::fake
。
如:
Soap::fake(function ($request) {
return Soap::response('Hello World', 200);
});
有一个使用 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
的自定义验证规则模拟 soap 响应?
您可以尝试这样的操作:
//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);
}
找到这个 laravel soap 包,它提供了一个易于使用的 Soap::fake
。
如:
Soap::fake(function ($request) {
return Soap::response('Hello World', 200);
});