Aller au contenu principal

Les mocks

Partie théorique

Qu'est-ce qu'un mock ?

Dans le domaine du développement logiciel, un mock est une simulation d'un objet réel utilisée pour tester le comportement de certains composants du logiciel.

Les mocks sont particulièrement utiles dans les tests unitaires, où ils peuvent être utilisés pour simuler le comportement d'objets dépendants afin de tester le comportement de l'objet cible dans des conditions contrôlées.

info

Les mocks sont généralement utilisés lorsque l'objet réel est imprévisible ou difficile à reproduire dans un environnement de test (par exemple, une base de données ou un service Web).

PHPUnit fournit un moyen facile de créer des mocks d'objets en PHP.

Exemple pratique

Supposons que nous avons une classe Fighter qui dépend d'une autre classe Arena.

Nous voulons tester la méthode fight de la classe Fighter, mais sans avoir à créer une véritable instance de Arena.

class Fighter {
private $arena;

public function __construct(Arena $arena) {
$this->arena = $arena;
}

public function fight() {
if ($this->arena->isOpen()) {
return "Le combat commence !";
} else {
return "L'arène est fermée.";
}
}
}

Nous pouvons créer un mock de Arena pour tester la méthode fight de Fighter :

public function testFight() {
// Création d'un mock pour la classe Arena
$arena = $this->createMock(Arena::class);

// Configuration du mock pour retourner true lorsque la méthode isOpen est appelée
$arena->method('isOpen')
->willReturn(true);

$fighter = new Fighter($arena);
$this->assertEquals("Le combat commence !", $fighter->fight());
}

Dans cet exemple :

  1. Nous créons un mock de Arena qui retourne toujours true lorsque la méthode isOpen est appelée.
  2. Nous utilisons ensuite ce mock pour tester la méthode fight de Fighter.
Pourquoi la classe Arena n'est pas implémentée ?

Lorsque vous créez un mock d'un objet (ici un objet Arena), vous n'avez pas besoin de la véritable implémentation de cet objet.

En fait, c'est l'un des principaux avantages de l'utilisation des mocks : vous pouvez tester le comportement d'un objet (ici un objet Fighter) indépendamment de ses dépendances (ici un objet Arena).

Lorsque vous créez un mock de l'objet Arena avec la ligne $arena = $this->createMock(Arena::class);, vous créez un faux objet Arena qui se comporte exactement comme vous le définissez dans votre test.

Dans cet exemple, vous définissez que la méthode isOpen de l'objet Arena mocké retourne toujours true.

Cela vous permet de contrôler précisément le comportement de l'objet Arena dans le cadre de votre test, sans avoir à vous soucier de la véritable implémentation de la classe Arena.

Test de mémorisation/compréhension


Qu'est-ce qu'un mock ?


Pourquoi utilise-t-on des mocks ?


Comment crée-t-on un mock avec PHPUnit ?


Que fait la méthode method sur un mock ?


Que fait la méthode willReturn sur un mock ?



TP pour réfléchir et résoudre des problèmes

Dans ce TP, nous allons tester la méthode rest de la classe Fighter.

Cette méthode doit retourner "Le combattant se repose." si l'arène est fermée, sinon elle doit retourner "Le combat continue, pas le temps de se reposer !".

  • Pour cela, nous allons créer un mock de la classe Arena qui retourne false lorsque la méthode isOpen est appelée.

  • Ensuite, nous utiliserons ce mock pour tester que la méthode rest de Fighter retourne "Le combattant se repose." lorsque l'arène est fermée.

Voici les étapes à suivre :

Étape 1 : Création d'une classe Arena minimale qui contient la méthode isOpen.

Voici comment vous pouvez le faire :

  1. Créez un nouveau fichier PHP nommé Arena.php.
  2. Dans ce fichier, déclarez une nouvelle classe appelée Arena.
  3. Dans la classe Arena, définissez une méthode publique isOpen qui retourne true par défaut.

Votre fichier Arena.php devrait ressembler à ceci :

class Arena {
public function isOpen() {
return true;
}
}

Maintenant, vous pouvez inclure la classe Arena dans vos fichiers Fighter.php et FighterTest.php en utilisant l'instruction require_once :

Étape 2 : Création de la classe Fighter

  1. Ouvrez votre éditeur de texte et créez un nouveau fichier PHP que vous nommerez Fighter.php.
  2. Dans ce fichier, déclarez une nouvelle classe appelée Fighter.
  3. Dans la classe Fighter, définissez un attribut privé $arena.
  4. Définissez un constructeur qui prend un objet Arena en paramètre et l'assigne à l'attribut $arena.
  5. Définissez une méthode publique rest qui retourne "Le combattant se repose." si l'arène est fermée, sinon elle retourne "Le combat continue, pas le temps de se reposer !".

Votre fichier Fighter.php devrait ressembler à ceci :

require_once 'Arena.php';

class Fighter {
private $arena;

public function __construct(Arena $arena) {
$this->arena = $arena;
}

public function rest() {
if (!$this->arena->isOpen()) {
return "Le combattant se repose.";
} else {
return "Le combat continue, pas le temps de se reposer !";
}
}
}

Étape 3 : Création du test unitaire

  1. Créez un nouveau fichier PHP que vous nommerez FighterTest.php.
  2. Dans ce fichier, déclarez une nouvelle classe appelée FighterTest qui étend PHPUnit\Framework\TestCase.
  3. Définissez une méthode public function testRest().
  4. Dans cette méthode, créez un mock de la classe Arena qui retourne false lorsque la méthode isOpen est appelée.
  5. Utilisez ce mock pour tester que la méthode rest de Fighter retourne "Le combattant se repose.".

Étape 4 : Exécution du test

  1. Ouvrez votre terminal, naviguez jusqu'au dossier contenant votre fichier FighterTest.php et exécutez le fichier avec la commande phpunit FighterTest.php. Vous devriez voir que le test passe, ce qui signifie que la méthode rest de Fighter se comporte comme prévu lorsque l'arène est fermée.
Une solution