Antes de ponerse a ver que son los dobles de prueba en phpunit creo que hay que leer sobre las pruebas unitarias con phpunit y sobre las aserciones.
Hay funcionalidades que no dependen de otros componentes y se pueden hacer pruebas unitarias sobre esas funcionalidades. Pero hay otras funcionalidades que dependen de otros componentes y probar esas funcionalidades pueden llevar a casos indeseados, como envío de emails o cobros indeseados. Muchos diréis que los sistemas de cobros tienen modo de pruebas y que en un sistema de envío de email se puede cambiar los emails de bbdd o deshabilitar el envío de emails de ese servidor o de la máquina local. En phpunit estas pruebas se llaman dobles de pruebas. Los dobles de prueba con phpunit consiste en crear clases stub y mock. La clase mock contendrá las funcionalidades que queremos evitar que se ejecuten, por ejemplo el envío de emails. Y la clase stub es la clase de pruebas que contiene la clase mock:
E el siguiente ejemplo se puede ver que tenemos una clase user y que se quiere probar que se le manda un email. Esta es la clase stub.
use PHPUnit\Framework\TestCase;
class UserTest extends TestCase
{
public function testNotificationIsSent()
{
$mock = $this->createMock(Mailer::class);
$mock->method('sendMessage')->willReturn(true);
$result = $mock->sendMessage('gonzalo@example.com', 'Hola');
$this->assertTrue($result);
}
En el ejemplo de arriba se crea el objeto mock y el parámetro es Mailer::class que es la clase definida abajo. Con el método $mock->method('sendMessage') se le indica que método de la calse mailer llamar y con el método >$mock->willReturn(true) se indica que tiene que devoler y hay realizar los asserts correspondientes.
class Mailer
{
/**
* Send a message
*
* @param string $email The email address
* @param string $message The message
*
* @return boolean True if sent, false otherwise
*/
public function sendMessage($email, $message)
{
if (empty($email)) {
throw new Exception;
}
// Use mail() or PHPMailer for example
sleep(3);
echo "send '$message' to '$email'";
return true;
}
}