Mockery is Better for SOAP Clients

Published in Testing, Mockery on Sep 15, 2021

Earlier today, I was testing a Service Class that accepted an instance of a SOAP Client to do what it needed to. The behavior I was trying to test was to ensure that it would handle SoapFault exceptions and failed responses from the service. In cases like this, you'd always be faking the responses of the web service to ensure that your test behaves consistently.

$client = $this->createMock(Client::class)
	->willThrowException(new SoapFault(0, 'Error Fetching http headers'));

This is what I initially wrote in my test body and when I first ran it, I was surprised by this error:

Trying to configure method "GetTxnToken" which cannot be configured because it does not exist, has not been specified, is final, or is static

Yes, there's a TestCase::getMockFromWsdl() method but since I was using Laravel, it was easy to extend Laravel's TestCase and use Mockery behind the scenes.

$client = $this->mock(Client::class)
	->andThrow(SoapFault::class, 'Error Fetching http headers');

This code would be fine but PHPStorm would squawk at me with this:

Expected parameter of type '\Laminas\Soap\Client', '\Mockery\Expectation|\Mockery\ExpectationInterface|\Mockery\HigherOrderMessage' provided

To avoid having to declare the type of $client in a docblock, I'd rather go with:

$client = Mockery::mock(Client::class);
	->andThrow(SoapFault::class, 'Error Fetching http headers');

PHPStorm would inspect $client as an instance of Laminas\Soap\Client|Mockery\LegacyMockInterface|Mockery\MockInterface which fits the expected type on the constructor of my Service Class.