Unit Testing Code which Consumes SOAP Services

Posted in PHP, Programming and Testing on Friday, the 10th of April, 2009.


One of the trickiest aspects of unit testing or Test Driving an application's code is testing those parts of the system which depend on an external system, such as a database or a SOAP service.

In this post I'll outline an approach to testing a class which happens to communicate with a third-party SOAP service using PHP's built-in SoapClient class. Hopefully, the principles involved will be applicable to the more general case of testing code which relies on an external system.


Posted by Ciaran McNulty on Friday, the 10th of April, 2009.

In your 'revised code' above, I'm not sure what you're gaining from the TranslationService's abstraction, if you're having to pass it a SoapClient instance.

Posted by Simon Harris on Friday, the 10th of April, 2009.

That's irrelevant, really.

I think you're questioning why the class exists in the first place, rather than why you want to make it testable? In which case I'll have to ask you to take a leap of faith that TranslationService - which is nothing more than example code - does "stuff". The nature of that stuff is really beyond the point of this post, but I do hint at it:

"some of the error handling, reformat SOAP responses into something more convenient...and so forth."

Point being, it has behaviour that you want to test.

Posted by Ciaran McNulty on Monday, the 13th of April, 2009.

The general point about testing SoapClients is very interesting, but I've a slight worry that in taking the instancing of the SoapClient outside your class, you'd be losing some of that valuable abstraction?

Maybe I'm making an assumption that you were trying to hide the fact it was a SOAP service? Mind you I've no better solution!

Posted by Simon Harris on Monday, the 13th of April, 2009.

I do see where you're coming from on that, and we do definitely want to hide the SOAPness of the service. So one thing that maybe I shouldn't have glossed over is the Factory. That plays an important role in all of this, and the rest of the app should never, ever be newing up TranslationService (and by implication, SoapClient). Doing that all over the place would suck in exactly the way I suspect you're keen to avoid.

Unfortunately PHP gives you limited means to enforce that. In Java, say, I'd imagine all the service wrappers to be in the same package, and their constructors marked package. The package's only public methods would be the Factory methods, so there would be no way for the rest of the app to new a TranslationService.

[Edit] I should also have mentioned that the "client code" could actually be inside TranslationService itself anyway, in a static getInstance() type method. But I'm splitting hairs about factories now, which is kind of what I wanted to avoid!

Posted by Charles Schaefer on Wednesday, the 2nd of December, 2009.

Just a feedback... PHPUnit has a Mock builder that creates Mock Objects from a WSDL file: http://www.phpunit.de/manual/current/en/test-do...GoogleTest.php.

Enter your comment: