Question Quelle est la différence entre faire semblant, se moquer, et piquer?


Je sais comment j'utilise ces termes, mais je me demande s'il existe des définitions acceptées feindre, railleur, et écrasement pour les tests unitaires? Comment les définissez-vous pour vos tests? Décrivez les situations dans lesquelles vous pourriez utiliser chacune.

Voici comment je les utilise:

Faux: une classe qui implémente une interface mais contient des données fixes et aucune logique. Renvoie simplement les données "bonnes" ou "mauvaises" en fonction de l'implémentation.

Moquer: une classe qui implémente une interface et permet de définir dynamiquement les valeurs à renvoyer / exceptions à lancer à partir de méthodes particulières et permet de vérifier si des méthodes particulières ont été appelées / non appelées.

Bout: Comme une classe fictive, sauf qu'elle ne permet pas de vérifier que les méthodes ont été appelées / non appelées.

Les mock et les stubs peuvent être générés à la main ou générés par un cadre de simulation. Les fausses classes sont générées à la main. J'utilise principalement des simulacres pour vérifier les interactions entre ma classe et les classes dépendantes. J'utilise des talons une fois que j'ai vérifié les interactions et que je teste d'autres chemins à travers mon code. J'utilise principalement des fausses classes pour extraire des dépendances de données ou lorsque des mock / stubs sont trop fastidieux pour être mis en place à chaque fois.


520
2017-12-06 15:17


origine


Réponses:


Vous pouvez obtenir des informations:

De Martin Fowler à propos de Mock and Stub

Faux les objets ont effectivement des implémentations de travail, mais prennent généralement un raccourci qui les rend impropres à la production

Stubs Fournir des réponses prédéfinies aux appels effectués pendant le test, ne répondant généralement pas à quoi que ce soit en dehors de ce qui est programmé pour le test. Les talons peuvent également enregistrer des informations sur les appels, comme un talon de passerelle de messagerie qui se souvient des messages qu'il a «envoyés» ou peut-être seulement sur le nombre de messages qu'il a «envoyés».

Mocks sont ce dont nous parlons ici: des objets préprogrammés avec des attentes qui forment une spécification des appels qu'ils sont censés recevoir.

De xunitpattern:

Faux: Nous acquérons ou construisons une implémentation très légère de la même fonctionnalité que celle fournie par un composant dont dépend le SUT et nous demandons au SUT de l'utiliser à la place du réel.

Bout : Cette implémentation est configurée pour répondre aux appels provenant du SUT avec les valeurs (ou exceptions) qui exerceront le code non testé (voir Bogues de production à la page X) dans le SUT. Une indication clé pour l'utilisation d'un talon de test est d'avoir un code non testé causé par l'incapacité de contrôler les entrées indirectes du SUT.

Objet mock qui implémente la même interface qu'un objet sur lequel dépend le SUT (System Under Test). Nous pouvons utiliser un objet Mock comme point d'observation lorsque nous devons effectuer une vérification de comportement pour éviter d'avoir une exigence non testée (voir Bugs de production à la page X) causée par l'incapacité d'observer les effets secondaires des méthodes invoquées sur le SUT.

Personnellement

J'essaie de simplifier en utilisant: Mock and Stub. J'utilise Mock quand c'est un objet qui renvoie une valeur qui est définie sur la classe testée. J'utilise Stub pour imiter une classe Interface ou Abstract à tester. En fait, peu importe ce que vous appelez, ce sont toutes des classes qui ne sont pas utilisées en production et qui sont utilisées comme classes utilitaires pour les tests.


423
2017-12-06 16:17



Bout - un objet qui fournit des réponses prédéfinies aux appels de méthode.

Moquer - un objet sur lequel vous définissez des attentes.

Faux - un objet avec des capacités limitées (à des fins de test), par ex. un faux service web.

Test Double est le terme général pour les talons, les faux et les faux. Mais informellement, vous entendrez souvent les gens les appeler simplement des simulacres.


157
2018-03-03 11:45



Je suis surpris que cette question existe depuis si longtemps et personne n'a encore fourni une réponse basée sur "L'art des tests unitaires" de Roy Osherove.

Dans "3.1 Introduction des stubs", vous définissez un stub comme suit:

Un stub est un remplacement contrôlable pour une dépendance existante   (ou collaborateur) dans le système. En utilisant un talon, vous pouvez tester votre code sans   traiter directement avec la dépendance.

Et définit la différence entre les talons et les faux comme:

La principale chose à retenir à propos des simulacres et des stubs est que les simulacres sont comme des stubs, mais vous vous opposez à l’objet simulé, alors que vous n’affirmez pas contre un stub.

Faux est juste le nom utilisé pour les deux stubs et les faux-semblants. Par exemple quand vous ne vous souciez pas de la distinction entre les talons et les faux-semblants.

La manière dont Osherove fait la distinction entre les souches et les simulacres signifie que toute classe utilisée comme un faux pour les tests peut être à la fois une souche ou un simulacre. Ce qui est pour un test spécifique dépend entièrement de la façon dont vous écrivez les contrôles dans votre test.

  • Lorsque votre test vérifie les valeurs dans la classe testée, ou en fait n'importe où sauf le faux, le faux a été utilisé comme un talon. Il ne fournissait que les valeurs à utiliser pour la classe testée, soit directement par les valeurs renvoyées par les appels sur celle-ci, soit indirectement en provoquant des effets secondaires (dans certains états) à la suite d'appels.
  • Lorsque votre test vérifie les valeurs du faux, il a été utilisé comme un faux.

Exemple de test où la classe FakeX est utilisée comme stub:

const pleaseReturn5 = 5;
var fake = new FakeX(pleaseReturn5);
var cut = new ClassUnderTest(fake);

cut.SquareIt;

Assert.AreEqual(25, cut.SomeProperty);

le fake instance est utilisée comme un talon parce que le Assert n'utilise pas fake du tout.

Exemple de test où la classe de test X est utilisée comme simulation:

const pleaseReturn5 = 5;
var fake = new FakeX(pleaseReturn5);
var cut = new ClassUnderTest(fake);

cut.SquareIt;

Assert.AreEqual(25, fake.SomeProperty);

Dans ce cas, le Assert vérifie une valeur sur fake, faisant de ce faux un faux.

Maintenant, bien sûr, ces exemples sont très artificiels, mais je vois un grand mérite dans cette distinction. Cela vous permet de savoir comment vous testez vos données et où sont les dépendances de votre test.

Je suis d'accord avec Osherove

Du point de vue de la maintenabilité pure, dans mes tests utilisant des mock crée plus de problèmes que de ne pas les utiliser. Cela a été mon expérience, mais j'apprends toujours quelque chose de nouveau.

Vous devez absolument éviter les fausses informations, car cela rend vos tests très dépendants de l'implémentation d'une classe qui n'est pas du tout testée. Ce qui signifie que les tests pour la classe ActualClassUnderTestpeut commencer à casser parce que la mise en œuvre pour ClassUsedAsMock modifié. Et ça me donne une odeur nauséabonde. Tests pour ActualClassUnderTest devrait de préférence seulement rompre lorsque ActualClassUnderTest est changé.

Je me rends compte que l'écriture d'affirmations contre le faux est une pratique courante, en particulier lorsque vous êtes un type d'abonné TDD. Je suppose que je suis fermement avec Martin Fowler dans le camp classique (Voir Les "Mocks ne sont pas des stubs" de Martin Fowler) et comme Osherove éviter les tests d'interaction (ce qui ne peut être fait en affirmant contre le faux) autant que possible.

Pour le plaisir de lire pourquoi vous devriez éviter les simulacres comme défini ici, google pour "fowler mockist classicist". Vous trouverez une pléthore d'opinions.


71
2017-10-25 18:03



Pour illustrer l'utilisation des stubs et des mock, je voudrais également inclure un exemple basé sur Roy Osherove "L'art des tests unitaires".

Imaginez, nous avons une application LogAnalyzer qui a pour seule fonctionnalité d’imprimer des journaux. Il n'a pas seulement besoin de parler à un service Web, mais si le service Web génère une erreur, LogAnalyzer doit enregistrer l'erreur dans une autre dépendance externe, en l'envoyant par courrier électronique à l'administrateur du service Web.

Voici la logique que nous aimerions tester dans LogAnalyzer:

if(fileName.Length<8)
{
 try
  {
    service.LogError("Filename too short:" + fileName);
  }
 catch (Exception e)
  {
    email.SendEmail("a","subject",e.Message);
  }
}

Comment testez-vous que LogAnalyzer appelle correctement le service de messagerie lorsque le service Web lève une exception? Voici les questions auxquelles nous sommes confrontés:

  • Comment pouvons-nous remplacer le service Web?

  • Comment pouvons-nous simuler une exception du service Web afin que nous puissions tester l'appel au service de messagerie?

  • Comment saurons-nous que le service de courriel a été appelé correctement ou à tout?

Nous pouvons traiter les deux premières questions en utiliser un talon pour le service Web. Pour résoudre le troisième problème, nous pouvons utiliser un objet simulé pour le service de messagerie.

Un faux est un terme générique qui peut être utilisé pour décrire un bout ou un simulacre. Dans notre test, nous aurons deux faux. L'un sera le service de courrier électronique, que nous allons utiliser pour vérifier que les paramètres corrects ont été envoyés au service de messagerie. L'autre sera un stub que nous utiliserons pour simuler une exception provenant du service web. C'est un stub, car nous n'utiliserons pas le service Web factice pour vérifier le résultat du test, mais pour nous assurer que le test fonctionne correctement. Le service de messagerie est un simulacre parce que nous affirmerons qu'il a été appelé correctement.

[TestFixture]
public class LogAnalyzer2Tests
{
[Test]
 public void Analyze_WebServiceThrows_SendsEmail()
 {
   StubService stubService = new StubService();
   stubService.ToThrow= new Exception("fake exception");
   MockEmailService mockEmail = new MockEmailService();

   LogAnalyzer2 log = new LogAnalyzer2();
   log.Service = stubService
   log.Email=mockEmail;
   string tooShortFileName="abc.ext";
   log.Analyze(tooShortFileName);

   Assert.AreEqual("a",mockEmail.To); //MOCKING USED
   Assert.AreEqual("fake exception",mockEmail.Body); //MOCKING USED
   Assert.AreEqual("subject",mockEmail.Subject);

 }
}

6
2018-04-06 03:12



Il s'agit de rendre les tests expressifs. Je fixe les attentes sur un Mock si je veux que le test décrive une relation entre deux objets. Je retourne des valeurs si je mets en place un objet de support pour m'apporter le comportement intéressant dans le test.


5
2018-05-21 18:36



Je vous connais Arrange-Act-Assert, alors une façon d'expliquer la différence entre stub et faux qui pourrait vous être utile, est que les stubs appartiennent à la section arrange, comme ils sont pour organiser l'état d'entrée, et les mocks appartiennent à la section assert comme ils sont pour affirmer des résultats contre.

Les nuls ne font rien. Ils servent uniquement à remplir des listes de paramètres, de sorte que vous n'obteniez pas d'erreurs non définies ou nuls. Ils existent également pour satisfaire le vérificateur de type dans les langues strictement typées, de sorte que vous pouvez être autorisé à compiler et à exécuter.


1
2018-03-29 11:13



la chose que vous affirmez, on l'appelle moquer objet et tout ce qui a juste aidé le test, est un bout.


0
2017-07-21 12:07