Tips for Making this Code Testable [migrated]
- by Jesse Bunch
So I'm writing an abstraction layer that wraps a telephony RESTful service for sending text messages and making phone calls. I should build this in such a way that the low-level provider, in this case Twilio, can be easily swapped without having to re-code the higher level interactions.
I'm using a package that is pre-built for Twilio and so I'm thinking that I need to create a wrapper interface to standardize the interaction between the Twilio service package and my application. Let us pretend that I cannot modify this pre-built package.
Here is what I have so far (in PHP):
<?php
namespace Telephony;
class Provider_Twilio implements Provider_Interface {
public function send_sms(Provider_Request_SMS $request) {
if (!$request->is_valid())
throw new Provider_Exception_InvalidRequest();
$sms = \Twilio\Twilio::request('SmsMessage');
$response = $sms->create(array(
'To' => $request->to,
'From' => $request->from,
'Body' => $request->body
));
if ($this->_did_request_fail($response)) {
throw new Provider_Exception_RequestFailed($response->message);
}
$response = new Provider_Response_SMS(TRUE);
return $response;
}
private function _did_request_fail($api_response) {
return isset($api_response->status);
}
}
So the idea is that I can write another file like this for any other telephony service provided that it implements Provider_Interface making them swappable. Here are my questions:
First off, do you think this is a good design? How could it be improved?
Second, I'm having a hard time testing this because I need to mock out the Twilio package so that I'm not actually depending on Twilio's API for my tests to pass or fail. Do you see any strategy for mocking this out?
Thanks in advance for any advice!