Je suis nouveau dans les tests unitaires et j'entends continuellement les mots «objets factices» jetés partout. En termes simples, quelqu'un peut-il expliquer ce que sont les objets simulés et à quoi ils sont généralement utilisés lors de l'écriture de tests unitaires?
unit-testing
mocking
agentbanks217
la source
la source
Réponses:
Puisque vous dites que vous êtes nouveau dans les tests unitaires et que vous avez demandé des objets fictifs en "termes simples", je vais essayer l'exemple d'un profane.
Test unitaire
Imaginez des tests unitaires pour ce système:
Il est généralement facile d'envisager de tester un composant de bas niveau comme
cook
:Le testeur commande simplement différents plats et vérifie que le cuisinier renvoie le plat correct pour chaque commande.
Il est plus difficile de tester un composant intermédiaire, comme le serveur, qui utilise le comportement d'autres composants. Un testeur naïf pourrait tester le composant serveur de la même manière que nous avons testé le composant cook:
Le pilote d'essai commandait différents plats et s'assurait que le serveur renvoie le bon plat. Malheureusement, cela signifie que ce test du composant serveur peut dépendre du comportement correct du composant de cuisson. Cette dépendance est encore pire si le composant cuisinier a des caractéristiques peu conviviales pour les tests, comme un comportement non déterministe (le menu comprend la surprise du chef comme plat), beaucoup de dépendances (le cuisinier ne cuisinera pas sans tout son personnel), ou beaucoup de ressources (certains plats nécessitent des ingrédients coûteux ou prennent une heure à cuire).
Puisqu'il s'agit d'un test de serveur, idéalement, nous voulons tester uniquement le serveur, pas le cuisinier. Plus précisément, nous voulons nous assurer que le serveur transmet correctement la commande du client au cuisinier et livre correctement la nourriture du cuisinier au client.
Le test unitaire signifie tester les unités indépendamment, donc une meilleure approche serait d'isoler le composant testé (le serveur) en utilisant ce que Fowler appelle des doubles de test (mannequins, stubs, faux, simulacres) .
Ici, le cuisinier de test est "de mèche" avec le pilote de test. Idéalement, le système testé est conçu de manière à ce que le cuisinier test puisse être facilement remplacé ( injecté ) pour travailler avec le serveur sans changer le code de production (par exemple sans changer le code serveur).
Objets simulés
Maintenant, le test cook (test double) pourrait être implémenté de différentes manières:
Voir l'article de Fowler pour plus de détails sur les faux vs les talons vs les mocks vs les mannequins , mais pour l'instant, concentrons-nous sur un simulacre de cuisinier.
Une grande partie des tests unitaires du composant serveur se concentre sur la manière dont le serveur interagit avec le composant cuisinier. Une approche basée sur des simulations se concentre sur la spécification complète de l'interaction correcte et sur la détection des dysfonctionnements.
L'objet fictif sait à l'avance ce qui est censé se passer pendant le test (par exemple, lequel de ses appels de méthodes sera invoqué, etc.) et l'objet fictif sait comment il est censé réagir (par exemple, quelle valeur de retour fournir). Le simulacre indiquera si ce qui se passe réellement diffère de ce qui est censé se produire. Un objet fictif personnalisé pourrait être créé à partir de zéro pour chaque cas de test afin d'exécuter le comportement attendu pour ce cas de test, mais un cadre de simulation s'efforce de permettre à une telle spécification de comportement d'être clairement et facilement indiquée directement dans le cas de test.
La conversation autour d'un test basé sur une simulation pourrait ressembler à ceci:
Mais comme notre serveur est nouveau, voici ce qui pourrait arriver:
ou
Il peut être difficile de voir clairement la différence entre les objets fictifs et les stubs sans un exemple contrastant basé sur les stub pour aller avec cela, mais cette réponse est déjà bien trop longue :-)
Notez également qu'il s'agit d'un exemple assez simpliste et que les frameworks moqueurs permettent des spécifications assez sophistiquées du comportement attendu des composants pour prendre en charge des tests complets. Il y a beaucoup de matériel sur les objets simulés et les frameworks moqueurs pour plus d'informations.
la source
Un objet simulé est un objet qui se substitue à un objet réel. Dans la programmation orientée objet, les objets fictifs sont des objets simulés qui imitent le comportement d'objets réels de manière contrôlée.
Un programmeur informatique crée généralement un objet simulé pour tester le comportement d'un autre objet, à peu près de la même manière qu'un concepteur de voiture utilise un mannequin de test de collision pour simuler le comportement dynamique d'un humain lors d'un impact sur un véhicule.
http://en.wikipedia.org/wiki/Mock_object
Les objets fictifs vous permettent de configurer des scénarios de test sans faire appel à des ressources volumineuses et lourdes telles que des bases de données. Au lieu d'appeler une base de données à des fins de test, vous pouvez simuler votre base de données à l'aide d'un objet fictif dans vos tests unitaires. Cela vous libère du fardeau d'avoir à configurer et à démolir une vraie base de données, juste pour tester une seule méthode dans votre classe.
Le mot «Mock» est parfois utilisé à tort de manière interchangeable avec «Stub». Les différences entre les deux mots sont décrites ici. Essentiellement, une maquette est un objet stub qui comprend également les attentes (c'est-à-dire les «assertions») pour le comportement correct de l'objet / de la méthode testée.
Par exemple:
Notez que les objets
warehouse
etmailer
fictifs sont programmés avec les résultats attendus.la source
Les objets simulés sont des objets simulés qui imitent le comportement des objets réels. En général, vous écrivez un objet fictif si:
la source
Un objet Mock est une sorte de Test Double . Vous utilisez des mockobjects pour tester et vérifier le protocole / l'interaction de la classe testée avec d'autres classes.
En règle générale, vous allez en quelque sorte des attentes de «programme» ou «d'enregistrement»: les appels de méthode que vous attendez de votre classe pour un objet sous-jacent.
Disons par exemple que nous testons une méthode de service pour mettre à jour un champ dans un widget. Et que dans votre architecture il y a un WidgetDAO qui s'occupe de la base de données. Parler avec la base de données est lent et la configuration et le nettoyage par la suite sont compliqués, nous allons donc nous moquer du WidgetDao.
pensons à ce que le service doit faire: il doit récupérer un widget de la base de données, faire quelque chose avec et l'enregistrer à nouveau.
Donc, en pseudo-langage avec une pseudo-fausse bibliothèque, nous aurions quelque chose comme:
De cette façon, nous pouvons facilement tester le développement de classes qui dépendent d'autres classes.
la source
Je recommande vivement un excellent article de Martin Fowler expliquant ce que sont exactement les simulacres et en quoi ils diffèrent des talons.
la source
Lors du test unitaire d'une partie d'un programme informatique, vous souhaitez idéalement tester uniquement le comportement de cette partie particulière.
Par exemple, regardez le pseudo-code ci-dessous à partir d'un morceau imaginaire d'un programme qui utilise un autre programme pour appeler print quelque chose:
Si vous testiez cela, vous voudriez principalement tester la partie qui regarde si l'utilisateur est Fred ou non. Vous ne voulez pas vraiment tester la
Printer
partie des choses. Ce serait un autre test.C'est là qu'interviennent les objets simulés. Ils prétendent être d'autres types de choses. Dans ce cas, vous utiliseriez une maquette
Printer
pour qu'elle agisse comme une vraie imprimante, mais ne ferait pas de choses gênantes comme l'impression.Il existe plusieurs autres types d'objets factices que vous pouvez utiliser qui ne sont pas des simulacres. La principale chose qui rend Mocks Mocks est qu'ils peuvent être configurés avec des comportements et des attentes.
Les attentes permettent à votre Mock de générer une erreur lorsqu'il n'est pas utilisé correctement. Ainsi, dans l'exemple ci-dessus, vous pouvez souhaiter être sûr que l'imprimante est appelée avec HelloFred dans le cas de test «l'utilisateur est Fred». Si cela ne se produit pas, votre Mock peut vous en avertir.
Le comportement dans Mocks signifie que, par exemple, de votre code a fait quelque chose comme:
Vous voulez maintenant tester ce que fait votre code lorsque l'imprimante est appelée et renvoie SaidHello, afin que vous puissiez configurer le Mock pour renvoyer SaidHello lorsqu'il est appelé avec HelloFred.
Une bonne ressource à ce sujet est Martin Fowlers post Mocks Arn't Stubs
la source
Les objets mock et stub sont une partie cruciale des tests unitaires. En fait, ils font beaucoup pour s'assurer que vous testez des unités plutôt que des groupes d'unités.
En un mot, vous utilisez des stubs pour briser la dépendance de SUT (System Under Test) sur d'autres objets et des simulations pour le faire et vérifier que SUT a appelé certaines méthodes / propriétés sur la dépendance. Cela revient aux principes fondamentaux des tests unitaires - que les tests doivent être facilement lisibles, rapides et ne nécessitant pas de configuration, ce qui pourrait impliquer l'utilisation de toutes les classes réelles.
En règle générale, vous pouvez avoir plus d'un stub dans votre test, mais vous ne devriez en avoir qu'un seul. En effet, le but de la simulation est de vérifier le comportement et votre test ne doit tester qu'une seule chose.
Scénario simple utilisant C # et Moq:
Dans l'exemple ci-dessus, j'ai utilisé Moq pour démontrer les stubs et les simulations. Moq utilise la même classe pour les deux -
Mock<T>
ce qui le rend un peu déroutant. Quoi qu'il en soit, au moment de l'exécution, le test échouera s'iloutput.Write
n'est pas appelé avec des données asparameter
, alors que l'échec de l'appelinput.Read()
n'échouera pas.la source
Comme une autre réponse suggérée via un lien vers "Les mocks ne sont pas des stubs ", les mocks sont une forme de "test double" à utiliser à la place d'un objet réel. Ce qui les différencie des autres formes de doubles de test, tels que les objets stub, est que d'autres doubles de test offrent une vérification d'état (et éventuellement une simulation) tandis que les simulacres offrent une vérification du comportement (et éventuellement une simulation).
Avec un stub, vous pouvez appeler plusieurs méthodes sur le stub dans n'importe quel ordre (ou même de manière répétitive) et déterminer le succès si le stub a capturé une valeur ou un état que vous vouliez. En revanche, un objet fictif s'attend à ce que des fonctions très spécifiques soient appelées, dans un ordre spécifique, et même un certain nombre de fois. Le test avec un objet fictif sera considéré comme "échoué" simplement parce que les méthodes ont été invoquées dans une séquence ou un nombre différent - même si l'objet fictif avait l'état correct à la fin du test!
De cette manière, les objets fictifs sont souvent considérés comme plus étroitement associés au code SUT que les objets stub. Cela peut être une bonne ou une mauvaise chose, selon ce que vous essayez de vérifier.
la source
Une partie de l'intérêt d'utiliser des objets fictifs est qu'ils n'ont pas à être vraiment implémentés selon les spécifications. Ils peuvent simplement donner des réponses factices. Par exemple, si vous devez implémenter les composants A et B, et que les deux "s'appellent" (interagissent avec), vous ne pouvez pas tester A tant que B n'est pas implémenté, et vice versa. Dans le développement piloté par les tests, c'est un problème. Donc, vous créez des objets simulés ("factices") pour A et B, qui sont très simples, mais ils donnent une sorte de réponse lorsqu'ils interagissent avec. De cette façon, vous pouvez implémenter et tester A à l'aide d'un objet fictif pour B.
la source
Pour php et phpunit est bien expliqué dans la documentation phpunit. vois ici documentation phpunit
Dans un simple mot, l'objet moqueur est juste un objet factice de votre original et renvoie sa valeur de retour, cette valeur de retour peut être utilisée dans la classe de test
la source
C'est l'une des principales perspectives des tests unitaires. oui, vous essayez de tester votre unité de code unique et vos résultats de test ne devraient pas être pertinents pour le comportement d'autres beans ou objets. vous devriez donc vous moquer d'eux en utilisant des objets Mock avec une réponse correspondante simplifiée.
la source