J'ai lu divers articles sur la moquerie contre le stubbing dans les tests, y compris les moqueries ne sont pas des talons de Martin Fowler , mais je ne comprends toujours pas la différence.
963
J'ai lu divers articles sur la moquerie contre le stubbing dans les tests, y compris les moqueries ne sont pas des talons de Martin Fowler , mais je ne comprends toujours pas la différence.
Réponses:
Talon
Je crois que la plus grande distinction est qu'un talon que vous avez déjà écrit avec un comportement prédéterminé. Ainsi, vous auriez une classe qui implémente la dépendance (classe abstraite ou interface la plus probable) que vous simulez à des fins de test et les méthodes seraient simplement tronquées avec des réponses définies. Ils ne feraient rien d'extraordinaire et vous auriez déjà écrit le code tronqué pour cela en dehors de votre test.
Moquer
Une maquette est quelque chose qui, dans le cadre de votre test, doit être configuré selon vos attentes. Une maquette n'est pas configurée d'une manière prédéterminée, vous avez donc du code qui le fait dans votre test. Les mocks d'une certaine manière sont déterminés lors de l'exécution, car le code qui définit les attentes doit s'exécuter avant de faire quoi que ce soit.
Différence entre les simulacres et les talons
Les tests écrits avec des
initialize -> set expectations -> exercise -> verify
simulations suivent généralement un modèle de test. Alors que le talon pré-écrit suivrait uninitialize -> exercise -> verify
.Similitude entre les simulacres et les talons
Le but des deux est d'éliminer le test de toutes les dépendances d'une classe ou d'une fonction afin que vos tests soient plus ciblés et plus simples dans ce qu'ils essaient de prouver.
la source
Préface
Il existe plusieurs définitions d'objets, qui ne sont pas réelles. Le terme général est test double . Ce terme englobe: mannequin , faux , talon , faux .
Référence
Selon l'article de Martin Fowler :
Style
Mocks vs Stubs = Test comportemental vs test d'état
Principe
Selon le principe du test, une seule chose par test , il peut y avoir plusieurs talons dans un test, mais généralement il n'y a qu'une seule maquette.
Cycle de la vie
Testez le cycle de vie avec des talons:
Testez le cycle de vie avec des simulacres:
Sommaire
Les tests de mocks et de stubs donnent une réponse à la question: quel est le résultat?
Les tests avec des simulations sont également intéressés par: Comment le résultat a-t-il été obtenu?
la source
Un talon est un simple faux objet. Il s'assure simplement que le test se déroule correctement.
Une maquette est un talon plus intelligent. Vous vérifiez que votre test le traverse.
la source
Voici une description de chacun suivi d'un échantillon du monde réel.
Factice - juste de fausses valeurs pour satisfaire le
API
.Fake - crée une implémentation de test d'une classe qui peut dépendre d'une infrastructure externe. (Il est recommandé que votre test unitaire n'interagisse PAS réellement avec l'infrastructure externe.)
Stub - substitue des méthodes pour renvoyer des valeurs codées en dur, également appelées
state-based
.Mock - très similaire
Stub
maisinteraction-based
basé sur un état. Cela signifie que vous ne vous attendez pasMock
à renvoyer une valeur, mais à supposer que l'ordre spécifique des appels de méthode est effectué.Stubs
etMocks
sont en fait des sous-types deMock
, à la fois échanger une implémentation réelle avec une implémentation de test, mais pour des raisons différentes et spécifiques.la source
Dans le cours codeschool.com , Rails Testing for Zombies , ils donnent cette définition des termes:
Talon
Moquer
Ainsi, comme Sean Copenhaver l'a décrit dans sa réponse, la différence est que les simulacres établissent des attentes (c'est-à-dire qu'ils font des affirmations, à savoir si ou comment ils sont appelés).
la source
Les talons n'échouent pas à vos tests, la maquette peut.
la source
Je pense que la réponse la plus simple et la plus claire à cette question est donnée par Roy Osherove dans son livre The art of Unit Testing (page 85)
Cela signifie que si vous faites des affirmations contre le faux, cela signifie que vous utilisez le faux comme une maquette, si vous utilisez le faux uniquement pour exécuter le test sans affirmation, vous utilisez le faux comme talon.
la source
En lisant toutes les explications ci-dessus, permettez-moi d'essayer de condenser:
la source
Un Mock teste simplement le comportement, en s'assurant que certaines méthodes sont appelées. Un Stub est une version testable (en soi) d'un objet particulier.
Que voulez-vous dire par Apple?
la source
Si vous le comparez au débogage:
la source
L'utilisation d'un modèle mental m'a vraiment aidé à comprendre cela, plutôt que toutes les explications et articles, qui ne «s'enfonçaient» pas tout à fait.
Imaginez que votre enfant a une plaque de verre sur la table et qu'il commence à jouer avec. Maintenant, vous avez peur que ça se casse. Alors, donnez-lui plutôt une assiette en plastique. Ce serait un Mock (même comportement, même interface, implémentation "plus douce").
Maintenant, disons que vous n'avez pas le remplacement en plastique, alors vous expliquez "Si vous continuez à jouer avec, il se cassera!". C'est un bout , vous avez fourni un état prédéfini à l'avance.
Un mannequin serait la fourchette qu'il n'utilisait même pas ... et un espion pourrait être quelque chose comme fournir la même explication que vous avez déjà utilisée qui fonctionnait.
la source
Je pense que la différence la plus importante entre eux est leurs intentions.
Permettez-moi d'essayer de l'expliquer dans POURQUOI talon vs POURQUOI maquette
Supposons que j'écris du code de test pour le contrôleur de chronologie publique de mon client mac twitter
Voici un exemple de code de test
En écrivant mock, vous découvrez la relation de collaboration des objets en vérifiant que les attentes sont satisfaites, tandis que stub ne simule que le comportement de l'objet.
Je suggère de lire cet article si vous essayez d'en savoir plus sur les simulacres: http://jmock.org/oopsla2004.pdf
la source
Pour être très clair et pratique:
Stub: une classe ou un objet qui implémente les méthodes de la classe / de l'objet à falsifier et renvoie toujours ce que vous voulez.
Exemple en JavaScript:
Mock: Identique à stub, mais il ajoute une logique qui "vérifie" lorsqu'une méthode est appelée afin que vous puissiez être sûr qu'une implémentation appelle cette méthode.
Comme le dit @mLevan, imaginez comme exemple que vous testez une classe d'enregistrement d'utilisateurs. Après avoir appelé Save, il doit appeler SendConfirmationEmail.
Un code très stupide Exemple:
la source
Cette diapositive explique très bien les principales différences.
* Extrait de la conférence 16 du CSE 403, Université de Washington (diapositive créée par "Marty Stepp")
la source
J'aime l'explication donnée par Roy Osherove [lien vidéo] .
la source
la source
voyons Test Doubles:
Stub : Stub est un objet qui contient des données prédéfinies et les utilise pour répondre aux appels pendant les tests. Tels que : un objet qui doit récupérer des données de la base de données pour répondre à un appel de méthode.
Mocks : les Mocks sont des objets qui enregistrent les appels qu'ils reçoivent. Dans l'assertion de test, nous pouvons vérifier sur Mocks que toutes les actions attendues ont été effectuées. Tels que : une fonctionnalité qui appelle le service d'envoi d'e-mails. pour en savoir plus, vérifiez ceci .
la source
Un faux est un terme générique qui peut être utilisé pour décrire soit un stub soit un faux objet (manuscrit ou autre), car ils ressemblent tous les deux au vrai objet.
Le fait qu'un faux soit un talon ou une maquette dépend de la façon dont il est utilisé dans le test actuel. S'il est utilisé pour vérifier une interaction (contre laquelle il est affirmé), il s'agit d'un objet factice. Sinon, c'est un talon.
Fakes garantit le bon déroulement du test. Cela signifie que le lecteur de votre futur test comprendra quel sera le comportement du faux objet, sans avoir besoin de lire son code source (sans avoir besoin de dépendre de ressources externes).
Que signifie le bon déroulement du test?
Par exemple dans le code ci-dessous:
Vous souhaitez tester la méthode mailService.SendEMail () , pour ce faire, vous devez simuler une exception dans votre méthode de test, il vous suffit donc de créer une classe Fake Stub errorService pour simuler ce résultat, puis votre code de test pourra tester méthode mailService.SendEMail (). Comme vous le voyez, vous devez simuler un résultat provenant d'une autre classe External Dependency ErrorService.
la source
Dès le papier Mock Roles, pas Objects , par les développeurs de jMock:
Ainsi, les principales différences sont:
Pour résumer, tout en essayant de dissiper la confusion du titre de l' article de Fowler : les simulacres sont des talons, mais ce ne sont pas seulement des talons .
la source
Je lisais L'art des tests unitaires et suis tombé sur la définition suivante:
la source
Je suis tombé sur cet article intéressant d'UncleBob The Little Mocker . Il explique toute la terminologie d'une manière très facile à comprendre, donc c'est utile pour les débutants. L'article de Martin Fowlers est difficile à lire, surtout pour les débutants comme moi.
la source
Talon nous aide à exécuter le test. Comment? Il donne des valeurs qui aident à exécuter le test. Ces valeurs ne sont pas elles-mêmes réelles et nous avons créé ces valeurs juste pour exécuter le test. Par exemple, nous créons un HashMap pour nous donner des valeurs similaires aux valeurs de la table de base de données. Ainsi, au lieu d'interagir directement avec la base de données, nous interagissons avec Hashmap.
Mock est un faux objet qui exécute le test. où nous mettons assert.
la source
Voir ci-dessous un exemple de simulations vs stubs utilisant le framework C # et Moq. Moq n'a pas de mot clé spécial pour Stub mais vous pouvez également utiliser l'objet Mock pour créer des stubs.
la source
Point de vue des tests de Stub and Mock:
Stub est une implémentation factice effectuée par l'utilisateur de manière statique , c'est-à-dire que Stub écrit le code d'implémentation. Il ne peut donc pas gérer la définition de service et la condition dynamique. Normalement, cela se fait dans le cadre JUnit sans utiliser le cadre de simulation.
Mock est également une implémentation factice, mais son implémentation est effectuée de manière dynamique en utilisant des frameworks Mocking comme Mockito. Nous pouvons donc gérer la définition des conditions et des services de manière dynamique, c'est-à-dire que les mocks peuvent être créés dynamiquement à partir du code lors de l'exécution. Donc, en utilisant mock, nous pouvons implémenter Stubs dynamiquement.
la source
Plus des réponses utiles, l'un des points les plus puissants de l'utilisation de Mocks than Subs
Si le collaborateur [dont le code principal en dépend] n'est pas sous notre contrôle (par exemple à partir d'une bibliothèque tierce),
dans ce cas, le stub est plus difficile à écrire qu'à se moquer .
la source
J'ai utilisé des exemples de python dans ma réponse pour illustrer les différences.
Stub - Stubbing est une technique de développement logiciel utilisée pour implémenter des méthodes de classes au début du cycle de vie du développement. Ils sont couramment utilisés comme espaces réservés pour l'implémentation d'une interface connue, où l'interface est finalisée ou connue mais l'implémentation n'est pas encore connue ou finalisée. Vous commencez avec des stubs, ce qui signifie simplement que vous écrivez uniquement la définition d'une fonction et laissez le code réel pour plus tard. L'avantage est que vous n'oublierez pas les méthodes et que vous pourrez continuer à penser à votre design tout en le voyant dans le code. Vous pouvez également demander à votre talon de renvoyer une réponse statique afin que la réponse puisse être utilisée par d'autres parties de votre code immédiatement. Les objets stub fournissent une réponse valide, mais c'est statique, quelle que soit l'entrée que vous transmettez, vous obtiendrez toujours la même réponse:
Moquer objets sont utilisés dans les scénarios de test fictifs, ils valident que certaines méthodes sont appelées sur ces objets. Les objets fantaisie sont des objets simulés qui imitent le comportement d'objets réels de manière contrôlée. Vous créez généralement un objet factice pour tester le comportement d'un autre objet. Les simulations nous permettent de simuler des ressources qui ne sont pas disponibles ou trop lourdes pour les tests unitaires.
mymodule.py:
test.py:
Il s'agit d'un exemple très basique qui exécute simplement rm et affirme le paramètre avec lequel il a été appelé. Vous pouvez utiliser une maquette avec des objets non seulement des fonctions comme indiqué ici, et vous pouvez également renvoyer une valeur afin qu'un objet maquette puisse être utilisé pour remplacer un stub pour le test.
Plus sur unittest.mock , notez qu'en python 2.x, le mock n'est pas inclus dans unittest mais est un module téléchargeable qui peut être téléchargé via pip (pip install mock).
J'ai également lu "The Art of Unit Testing" de Roy Osherove et je pense que ce serait génial si un livre similaire était écrit en utilisant des exemples Python et Python. Si quelqu'un connaît un tel livre, merci de le partager. À votre santé :)
la source
Un stub est un faux objet construit à des fins de test. Une maquette est un talon qui enregistre si les appels attendus se sont effectivement produits.
la source
Un stub est une fonction vide qui est utilisée pour éviter les exceptions non gérées pendant les tests:
Une maquette est une fonction artificielle utilisée pour éviter les dépendances du système d'exploitation, de l'environnement ou du matériel pendant les tests:
En termes d'affirmations et d'état:
Références
la source
beaucoup de réponses valables là-haut, mais je pense qu'il vaut la peine de mentionner cette forme oncle bob: https://8thlight.com/blog/uncle-bob/2014/05/14/TheLittleMocker.html
la meilleure explication jamais avec des exemples!
la source
Une maquette est à la fois un objet technique et fonctionnel .
La maquette est technique . Il est en effet créé par une bibliothèque fictive (EasyMock, JMockit et plus récemment Mockito sont connus pour ceux-ci) grâce à la génération de code octet .
L'implémentation fictive est générée de manière à pouvoir l' instrumenter pour renvoyer une valeur spécifique lorsqu'une méthode est invoquée, mais aussi d'autres choses telles que la vérification qu'une méthode fictive a été invoquée avec certains paramètres spécifiques (contrôle strict) ou quels que soient les paramètres ( pas de contrôle strict).
Instanciation d'une simulation:
Enregistrer un comportement:
Vérification d'une invocation:
Ce n'est clairement pas le moyen naturel d'instancier / remplacer la classe / le comportement Foo. C'est pourquoi je me réfère à un aspect technique.
Mais la maquette est également fonctionnelle car c'est une instance de la classe que nous devons isoler du SUT. Et avec des comportements enregistrés dessus, nous pourrions l'utiliser dans le SUT de la même manière que nous le ferions avec un talon.
Le stub n'est qu'un objet fonctionnel : c'est une instance de la classe que nous devons isoler du SUT et c'est tout. Cela signifie que la classe de stub et tous les agencements de comportements nécessaires lors de nos tests unitaires doivent être définis explicitement.
Par exemple, pour stub,
hello()
il faudrait sous-Foo
classer la classe (ou implémenter son interface, il l'a) et remplacerhello()
:Si un autre scénario de test nécessite un autre retour de valeur, nous aurions probablement besoin de définir une manière générique de définir le retour:
Autre scénario: si j'avais une méthode d'effet secondaire (pas de retour) et que je vérifierais que cette méthode a été invoquée, j'aurais probablement dû ajouter un booléen ou un compteur dans la classe stub pour compter combien de fois la méthode a été invoquée.
Conclusion
Le stub nécessite souvent beaucoup de surcharge / code pour écrire pour votre test unitaire. Ce que la simulation empêche grâce aux fonctionnalités d'enregistrement / de vérification prêtes à l'emploi.
C'est pourquoi de nos jours, l'approche stub est rarement utilisée dans la pratique avec l'avènement d'excellentes bibliothèques fictives.
À propos de l'article de Martin Fowler: Je ne pense pas être un programmeur "moqueur" lorsque j'utilise des simulacres et j'évite les talons.
Mais j'utilise la simulation quand c'est vraiment nécessaire (dépendances gênantes) et je privilégie les tests de découpage et les tests de mini-intégration lorsque je teste une classe avec des dépendances dont la simulation serait une surcharge.
la source