I am writing some unit test for some legacy code as a preparation for some refactoring.
One section of the code is calling a class from a third-party library (I cannot change the code in it).
The code is using its constructor and calling some static variable.
May I ask how can I mock the method for testing? (or how do I test the method without mocking?)
I have tried to simplify my code for an example:
/////////////////////////////////////////////////////////////////////
// This is from the library code that I am unable to change
class ResponseMessage
{
const STATUS_ERROR = 500;
const STATUS_SUCCESS = 200;
function __construct( $responseMessage, $responseCode ) {
$this->responseMessage = $responseMessage;
$this->responseCode = $responseCode
}
public function sendMessage($sendToAdmin = false) {
if ($sendToAdmin) {
$targetEmailAddress = $this->emailAddresses['admin'];
$targetAPISettings = $this->apiSettings['admin'];
}
else {
$targetEmailAddress = $this->emailAddresses['customer'];
$targetAPISettings = $this->apiSettings['customer'];
}
$this->triggerSendEmail($targetEmailAddress);
$this->triggerAPI($targetAPISettings);
}
//.... Some other methods and variables
}
/////////////////////////////////////////////////////////////////////
// This is my class to be tested. If possible I would like to avoid
// changing any code, but if it is necessary this code can be changed
// a bit for injecting mock class.
class myClass
{
// ... some other methods where I have no problem testing....
function handle($input) {
//The actual comparison is much more complicated. Simplified for my question
if (empty($input)) {
// Some other error handling, no response message is generated
return;
}
if ( $input == 1 )
$responseMessage = new ResponseMessage('The input is 1', ResponseMessage::STATUS_SUCCESS );
else if ( $input == 2 )
$responseMessage = new ResponseMessage('The input is 2', ResponseMessage::STATUS_SUCCESS );
else
$responseMessage = new ResponseMessage('Unexpected input', ResponseMessage::STATUS_ERROR );
$respnoseMessage->sendMessage();
$responseMessageToAdmin = new ResponseMessage('The comaparison is triggered', RespnoseMessage::STATUS_SUCCESS);
$responseMessageToAdmin->sendMessage(true);
}
}
///////////////////////////////////////////////////////////////////
// This is my PHPUnit testing class
class testMyClass
{
public function testProcessWithInputOne {
// how should I mock ResponseMessage here?
/////////////////////////////////////////////////////////
// These are not going to work, but tried to write some code to demo what I want to test.
$mockResponseMessage = Mockery::mock('alias:ResponseMessage');//used alias for simplicity, but mocking it normally and inject the mocked object is also acceptable.
$mockResponseMessage->setConst('STATUS_SUCCESS', 200);
$mockResponseMessage->shouldReceive('__construct')->with('The input is 1', 200)->once()->andReturn($mockResponseMessage);
$mockResponseMessage->shouldReceive('sendMessage')->with(false)->once(); //here with(false) is testing no argument is passed as the default argument value is false
$mockResponseMessage->shouldReceive('__construct')->with('The comaparison is triggered', 200)->once()->andReturn($mockResponseMessage);
$mockResponseMessage->shouldReceive('sendMessage')->with(true)->once();
/////////////////////////////////////////////////////////
$myClass = new MyClass();
$myClass->handle(1);
}
}
How to write unit test testMyClass
for code (class myClass
) calling a class from a library ResponseMessage
with public constants (ResponseMessage::STATUS_ERROR
, ...::STATUS_SUCCESS
) and constructor ResponseMessage::__construct()
?