55 votes

Pourquoi est-il si mauvais de se moquer des cours?

J'ai récemment discuté avec un collègue au sujet de moqueries. Il a dit que les moqueries des classes est très mauvais et ne doit pas être fait, dans quelques cas.

Il dit que seuls les interfaces doivent être l'objet de moqueries, sinon c'est une architecture faute.

Je me demande pourquoi cette déclaration (j'ai entièrement confiance en lui) est donc correct? Je ne sais pas et je voudrais être convaincu.

J'ai manqué le point de se moquer (oui, j'ai lu Martin Fowler article)

70voto

Jon Skeet Points 692016

Se moquant est utilisé pour le protocole de test - il teste la façon dont vous allez utiliser une API, et comment vous allez réagir lorsque l'API réagit en conséquence.

Idéalement (dans de nombreux cas, au moins), que l'API doit être spécifié comme une interface plutôt qu'une classe - une interface définit un protocole, une classe définit au moins une partie de la mise en œuvre.

Sur une note pratique, se moquant de cadres ont tendance à avoir des limites autour de se moquant de classes.

Dans mon expérience, en se moquant est quelque peu galvaudé - souvent vous n'êtes pas vraiment intéressé à l'interaction exacte, vous voulez vraiment un stub... mais se moquant de cadre peut être utilisé pour créer des talons, et vous tombez dans le piège de la création d'fragile tests en se moquant au lieu de cogner. C'est un équilibre difficile à obtenir que le droit.

26voto

Pascal Thivent Points 295221

IMHO, ce que votre collègue veut dire, c'est que vous devriez programmer une interface, pas une implémentation . Si vous vous retrouvez trop souvent en train de vous moquer des cours, cela signifie que vous avez brisé le principe précédent lors de la conception de votre architecture.

16voto

Stefan Steinegger Points 37073

Se moquant de classes (contrairement aux moqueries des interfaces) est mauvais parce que la maquette a encore une vraie classe dans le fond, c'est héréditaire, et il est possible que la mise en oeuvre réelle est exécuté lors de l'essai.

Lorsque vous vous moquez (ou talon de chèque, ou quoi que ce soit) une interface, il n'y a pas de risque d'avoir le code d'exécution, vous en fait voulu se moquer.

Les moqueries, les classes vous oblige à faire tout ce qui pourrait éventuellement être l'objet de moqueries, d'être virtuel, qui est très envahissante et pourrait conduire à la mauvaise conception de classe.

Si vous souhaitez dissocier les classes, ils ne devraient pas connaître les uns les autres, c'est la raison pour laquelle il est logique de se moquer (ou talon de chèque, ou quoi que ce soit) l'un d'eux. Donc, la mise en œuvre à l'aide d'interfaces est recommandé de toute façon, mais ce qui est mentionné ici par d'autres assez.

6voto

Anderson Imes Points 18093

En général, vous voulez pour se moquer d'une interface.

Alors qu'il est possible de simuler une classe ordinaire, il tend à influencer la conception des classes trop pour la testabilité. Des préoccupations comme l'accessibilité, l'existence ou non d'une méthode est virtuelle, etc. tous sera déterminée par la capacité à se moquer de la classe, plutôt que de vrai OO préoccupations.

Il y a un semblant bibliothèque appelée TypeMock Isolateur qui vous permet de contourner ces limitations (ont gâteau, manger du gâteau) mais c'est assez cher. Mieux à la conception pour la testabilité.

2voto

Graviton Points 28358

Edit: Depuis que vous avez précisé que votre collègue signifie se moquer de classe est mauvaise, mais se moquer de l'interface n'est pas, la réponse ci-dessous est obsolète. Vous devriez vous référer à cette réponse.

Je parle de la maquette et le talon comme défini par Martin Fowler, et je suppose que c'est ce que votre collègue voulait dire, trop.

Se moquant est mauvais, car il peut conduire à overspecification de tests. L'utilisation de stub, si possible, et éviter de se moquer.

Voici la diff entre la maquette et le stub (à partir de l'article ci-dessus):

Nous pouvons alors utiliser la vérification de l'état sur le stub comme ça.

class OrderStateTester...
  public void testOrderSendsMailIfUnfilled() {
    Order order = new Order(TALISKER, 51);
    MailServiceStub mailer = new MailServiceStub();
    order.setMailer(mailer);
    order.fill(warehouse);
    assertEquals(1, mailer.numberSent());
  }

Bien sûr, c'est une épreuve très simple - seulement qu'un message a été envoyé. Nous n'avons pas testé, il a été envoyé à l' droit de la personne, ou le droit contenu, mais il le fera pour illustrer le point.

L'aide se moque de ce test un aspect très différentes.

class OrderInteractionTester...
  public void testOrderSendsMailIfUnfilled() {
    Order order = new Order(TALISKER, 51);
    Mock warehouse = mock(Warehouse.class);
    Mock mailer = mock(MailService.class);
    order.setMailer((MailService) mailer.proxy());

    mailer.expects(once()).method("send");
    warehouse.expects(once()).method("hasInventory")
      .withAnyArguments()
      .will(returnValue(false));

    order.fill((Warehouse) warehouse.proxy());
  }
}

Pour utiliser la vérification de l'état sur le talon, j'ai besoin de faire quelques méthodes supplémentaires sur l' >talon pour aider à la vérification. En conséquence, le stub implémente MailService mais ajoute des >méthodes d'essai.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X