web-dev-qa-db-fra.com

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

J'ai récemment discuté avec un collègue sur la moqueur. Il a dit que des cours moqueurs sont très mauvais et ne devraient pas être faits, ce n'est que dans quelques cas.

Il dit que seules les interfaces devraient être moquées, sinon c'est une faute d'architecture.

Je me demande pourquoi cette déclaration (je lui faisais bien confiance) est si correcte? Je ne le sais pas et je voudrais être convaincu.

Ai-je manqué le point de moqueur (oui, j'ai lu article de Martin Fowler )

42
guerda

La moqueur est utilisée pour -protocole Test - il teste comment vous utiliserez une API et comment réagirez lorsque l'API réagit en conséquence.

Idéalement (dans de nombreux cas au moins), que l'API devrait être spécifiée comme une interface plutôt qu'une interface de classe - une interface définit un protocole, une classe définit au moins une partie d'une implémentation.

Sur une note pratique, les cadres moqueurs ont tendance à avoir des limitations autour des cours moqueurs.

Dans mon expérience, on se moque quelque peu surutilisé - souvent vous n'êtes pas vraiment intéressé par l'interaction exacte, vous voulez vraiment un Stub ... mais un cadre moqueur peut être utilisé pour créer des talons et vous tombez dans le piège de créer des tests fragiles en se moquant au lieu de l'encaissement. C'est un équilibre difficile à suivre.

59
Jon Skeet

IMHO, ce que votre collègue signifie que vous devriez programme à une interface, pas une implémentation . Si vous vous moquez de casse-toi trop souvent, c'est un signe que vous avez brisé le principe précédent lors de la conception de votre architecture.

22
Pascal Thivent

Les classes moqueuses (contrairement aux interfaces moqueuses) sont mauvaises car la simulation a toujours une véritable classe en arrière-plan, elle est héritée, et il est possible que la mise en œuvre réelle est exécutée pendant le test.

Lorsque vous vous moquez (ou talon ou autre) une interface, il n'y a aucun risque d'avoir exécuté du code que vous vouliez réellement se moquer.

Les classes moqueurs vous oblige également à faire tout, qui pourrait éventuellement être moquée, pour être virtuel, qui est très intrusif et pourrait conduire à conception de la classe mauvaise.

Si vous souhaitez découpler des cours, ils ne devraient pas se connaître, c'est la raison pour laquelle il est logique de se moquer (ou de le talon ou autre) l'un d'entre eux. Il est donc recommandé de mettre en œuvre contre les interfaces, mais cela est suffisamment mentionné ici par d'autres.

14
Stefan Steinegger

Généralement, vous voudriez se moquer d'une interface.

Bien qu'il soit possible de se moquer d'une classe normale, il a tendance à influencer votre conception de classe trop pour la qualification. Les préoccupations telles que Accessibilité, une méthode ou non est virtuelle, etc. seront toutes déterminées par la capacité de se moquer de la classe, plutôt que true OO Course.

Il y a une bibliothèque de simulation appelée Typemock Isolator qui vous permet de contourner ces limitations (avoir un gâteau, manger du gâteau) mais c'est assez cher. Mieux vaut concevoir pour la qualification.

4
Anderson Imes

Edit: Puisque vous avez précisé que votre collègue signifiait classe simulée est mauvais, mais faux Interface n'est pas, la réponse ci-dessous est obsolète. Vous devez 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 ce que votre collègue voulais dire, aussi.

Mocking est mauvaise parce qu'elle peut conduire à surspécification des tests. Utilisez stub si possible et éviter la maquette.

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

On peut alors utiliser la vérification de l'état sur le talon comme celui-ci.

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, cela est un test très simple - seulement qu'un message a été envoyé. Nous ne l'avons pas testé a été envoyé à la bonne personne, ou avec le contenu à droite, mais il le fera pour illustrer ce point.

En utilisant ce test se moque un aspect très différent.

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, je dois faire quelques méthodes supplémentaires sur le> stub à l'aide à la vérification. En conséquence, les outils stub MailService mais ajoute supplémentaires> méthodes d'essai.

2
Graviton

Je suggérerais de rester à l'écart des cadres moqueurs autant que possible. Dans le même temps, je recommanderais d'utiliser des objets simulés/faux pour tester, autant que possible. L'astuce ici est que vous devriez créer objets fausses intégrés avec des objets réels. Je l'explique plus en détail dans un article de blog que j'ai écrit à ce sujet: http://www.yegor256.com/2014/09/23/built-in-fake-Object.html

2
yegor256

Il est logique de se moquer de classes afin que les tests peuvent être écrits tôt dans le cycle de vie du développement.

Il y a une tendance à continuer d'utiliser des classes simulées, même lorsque des implémentations concrètes deviennent disponibles. Il y a aussi la tendance à se développer contre des classes (et des talons) faciles nécessaires au début d'un projet lorsque certaines parties du système n'ont pas été construites.

Une fois qu'un morceau du système a été construit, il est nécessaire de les tester et de continuer à tester contre elle (pour la régression). Dans ce cas, commencer par des simulacres est bon, mais ils devraient être jetés en faveur de la mise en œuvre dès que possible. J'ai vu des projets difficilement parce que différentes équipes continuent de se développer contre le comportement de la simulation plutôt que de la mise en œuvre (une fois qu'il est disponible).

En testant des simulacres, vous supposez que la simulation est caractéristique du système. Cela implique souvent de deviner ce que le composant moqueur fera. Si vous avez une spécification du système, vous ne vous moquez que vous n'avez pas à deviner, mais souvent, le système "comme construit" ne correspond à la spécification d'origine en raison de considérations pratiques découvertes lors de la construction. Les projets de développement agiles supposent que cela se produira toujours.

Vous développez ensuite du code qui fonctionne avec la simulation. Quand il s'avère que la simulation ne représente pas vraiment le comportement du système réel AS-construit (par exemple, des problèmes de latence non observés dans les problèmes de moqueur, de ressources et d'efficacité non observés dans les problèmes de performance, etc.), etc.) vous Avoir un tas d'essais moqueurs sans valeur que vous devez maintenant maintenir.

Je considère que l'utilisation de moqueurs d'être précieuse au début du développement, mais ces moqueurs ne doivent pas contribuer à la couverture du projet. Il est préférable que les simulacres sont supprimés et que les tests d'intégration appropriés sont créés pour les remplacer, sinon votre système ne sera pas testé pour la variété des conditions que votre simulation n'a pas simulé (ou simule de manière incorrecte par rapport au système réel).

Donc, la question est de savoir si vous utilisez ou non des simulacres, il est question de les utiliser et de les supprimer.

0
Moa

La réponse, comme la plupart des questions sur les pratiques, est "cela dépend".

La surutilisation de simulacres peut conduire à des tests qui ne testent pas vraiment rien. Cela peut également entraîner des tests qui constituent une réémission virtuelle du code sous test, étroitement liée à une implémentation spécifique.

D'autre part, une utilisation judicieuse des simulacres et des talons peut entraîner des tests unitaires qui sont soigneusement isolés et testent une seule chose et une seule chose qui est une bonne chose.

Tout est question de modération.

0
Avdi