web-dev-qa-db-fra.com

Mock framework vs MS Fakes cadres

Un peu confus sur les différences entre les frameworks Mock tels que NMock vs le framework VS 2011 Fakes. D'après MSDN, si j'ai bien compris, Fakes vous permet de vous moquer de vos dépendances, tout comme RhinoMock ou NMock. Cependant, l'approche est différente. Fakes génère du code pour obtenir cette fonctionnalité, contrairement à la structure Mocks. Alors ma compréhension est-elle correcte? Fakes est-il juste un autre cadre factice?

91
Nairooz NIlafdeen

Votre question portait sur la différence entre le framework MS Fakes et celui de NMock. Il semble que les autres réponses en aient résolu une partie, mais voici quelques informations supplémentaires sur la manière dont elles sont identiques et différentes. NMock est également similaire à RhinoMocks et Moq, je les regroupe donc avec NMock.

Je vois tout de suite trois différences majeures entre NMock/RhinoMocks/Moq et MS Fakes Framework:

  • Le cadre fictif de MS utilise le code généré, un peu comme les accesseurs des versions précédentes de Visual Studio, au lieu des types génériques. Lorsque vous souhaitez utiliser le faux framework pour une dépendance, vous ajoutez l'assembly contenant la dépendance aux références du projet test, puis cliquez dessus avec le bouton droit de la souris pour générer les doublons de test (talons ou cales). Ensuite, lorsque vous testez, vous utilisez plutôt ces classes générées. NMock utilise des génériques pour accomplir la même chose (c'est-à-dire IStudentRepository studentRepository = mocks.NewMock<IStudentRepository>()). À mon avis, l'approche du cadre MS Fakes inhibe la navigation dans le code et le refactoring à partir des tests, car vous travaillez en réalité contre une classe générée, et non votre véritable interface.

  • Le cadre fictif de MS fournit des moignons et des taupes (cales), alors que NMock, RhinoMocks et Moq fournissent tous des moignons et mock. Je ne comprends vraiment pas la décision de MS de ne pas inclure les imitations et je ne suis personnellement pas un adepte des taupes pour les raisons décrites ci-dessous.

  • Avec le framework MS fakes, vous fournissez une implémentation alternative des méthodes que vous souhaitez remplacer. Au sein de ces autres implémentations, vous pouvez spécifier les valeurs de retour et suivre les informations sur le mode ou le nom de la méthode. Avec NMock, RhinoMocks et Moq, vous générez un objet fictif, que vous utiliserez ensuite pour spécifier des valeurs de retour stubbed ou pour suivre les interactions (si et comment les méthodes ont été appelées). Je trouve l’approche factice MS plus complexe et moins expressive.

Pour clarifier la différence entre ce que fournissent les frameworks: NMock, RhinoMocks et Moq fournissent tous deux types de doubles de test (stubs et mock). Le faux cadre fournit des moignons et des taupes (on les appelle des cales) et, malheureusement, ne comprend pas de faux. Afin de comprendre les différences et les similitudes entre NMock et MS Fakes, il est utile de comprendre quels sont ces différents types de tests en double:

Stubs: Les stubs sont utilisés lorsque vous devez fournir une valeur aux méthodes ou propriétés qui seront demandées à vos doublons de test par la méthode testée. Par exemple, lorsque ma méthode sous test appelle double la méthode DoesStudentExist () du test IStudentRepository, je souhaite qu’elle renvoie true.

L'idée de stubs dans NMock et MS fakes est la même, mais avec NMock, vous feriez quelque chose comme ceci:

Stub.On(mockStudentRepository).Method("DoesStudentExist").Will(Return.Value(true));

Et avec MSFakes, vous feriez quelque chose comme ça:

IStudentRepository studentRepository = new DataAccess.Fakes.StubIStudentRepository() // Generated by Fakes.
{
    DoesStudentExistInt32 = (studentId) => { return new Student(); }
};

Notez que dans l'exemple MS Fakes, vous créez une implémentation entièrement nouvelle pour la méthode DoesStudentExist (notez qu'il s'appelle DoesStudentExistInt32 car le framework fakes ajoute les types de données de paramètre aux noms de méthode lorsqu'il génère les objets de stub. les tests). Pour être honnête, l'implémentation de NMock me perturbe également car elle utilise une chaîne pour identifier le nom de la méthode. (Pardonnez-moi si j'ai mal compris comment NMock est destiné à être utilisé.) Cette approche empêche vraiment le refactoring et je recommanderais vivement RhinoMocks ou Moq à NMock pour cette raison.

Mocks: Les mocks sont utilisés pour vérifier l'interaction entre votre méthode testée et ses dépendances. Avec NMock, vous le faites en définissant des attentes similaires à celles-ci:

Expect.Once.On(mockStudentRepository).Method("Find").With(123);

C’est une autre raison pour laquelle je préférerais RhinoMocks et Moq à NMock. NMock utilise le style d’attente plus ancien, tandis que RhinoMocks et Moq prennent en charge l’approche Arrange/Act/Assert, dans laquelle vous spécifiez les interactions attendues à la fin du test, comme ceci. :

stubStudentRepository.AssertWasCalled( x => x.Find(123));

Encore une fois, notez que RhinoMocks utilise un lambda au lieu d'une chaîne pour identifier la méthode. Le framework ms fakes ne fournit pas de simulacre du tout. Cela signifie que, dans vos implémentations stubbed-out (voir la description des stubs ci-dessus), vous devez définir des variables que vous avez vérifiées par la suite. Cela ressemblerait à ceci:

bool wasFindCalled = false;

IStudentRepository studentRepository = new DataAccess.Fakes.StubIStudentRepository() 
{
    DoesStudentExistInt32 = (studentId) => 
        { 
            wasFindCalled = true;
            return new Student(); 
        }
};

classUnderTest.MethodUnderTest();

Assert.IsTrue(wasFindCalled);

Je trouve cette approche un peu compliquée puisqu'il faut suivre l'appel dans le talon, puis l'affirmer plus tard au cours du test. Je trouve que les exemples NMock, et en particulier RhinoMocks, sont plus expressifs.

Moles (Shims): Pour être franc, je n'aime pas les taupes, en raison de leur potentiel d'utilisation abusive. Une des choses que j'aime tant dans les tests unitaires (et TDD en particulier) est que le test de votre code vous aide à comprendre où vous avez écrit du code de mauvaise qualité. En effet, tester du code mal écrit est difficile. Ce n'est pas vrai lorsque vous utilisez des taupes, car elles sont conçues pour vous permettre de tester des dépendances non injectées ou de tester des méthodes privées. Ils fonctionnent de la même manière que les stubs, sauf que vous utilisez un ShimsContext comme ceci:

using (ShimsContext.Create())
{
    System.Fakes.ShimDateTime.NowGet = () => { return new DateTime(fixedYear, 1, 1); };
}

Ce qui m'inquiète, c'est que les gens vont commencer à les voir comme "un moyen plus facile de tester l'unité", car cela ne vous oblige pas à écrire du code comme vous le devriez. Pour un compte-rendu plus complet sur ce concept, consultez ce post:

Pour plus d'informations sur certaines préoccupations liées aux faux cadres, consultez ces articles:

Si vous souhaitez apprendre à RhinoMocks, voici une vidéo de formation Pluralsight (divulgation complète - j'ai écrit ce cours et perçu des royalties pour les vues, mais je pense que cela s'applique à cette discussion, donc je l'inclus ici):

180
Jim Cooper

Vous avez raison, mais il y a plus dans l'histoire. Les points les plus importants à retenir de cette réponse sont:

  1. Votre architecture doit utiliser correctement les stubs et l'injection de dépendance, plutôt que de compter sur la béquille de Fakes et de moqueurs

  2. Les faux et les faux sont utiles pour tester du code que vous ne devriez pas ou ne pouvez pas changer, tel que:

    • Code hérité qui ne fait pas usage (ou utilisation efficace) de stubs
    • API tierces
    • Ressources pour lesquelles vous n'avez pas de code source

Shims (connu sous le nom de "Moles", en cours de développement) est en effet un cadre moqueur qui fonctionne par le biais d'appels de déviation. Au lieu de construire laborieusement une maquette (oui, même utiliser Moq est relativement pénible!), Shims utilise simplement l'objet de code de production déjà en place. Shims redirige simplement l'appel de la cible de production vers le délégué de test.

Stubs sont générés à partir des interfaces du projet cible. L'objet Stub n'est que cela - une implémentation de l'interface. L'avantage d'utiliser le type Stub est que vous pouvez générer rapidement un stub sans encombrer votre projet de test avec de nombreux stubs à usage unique, sans parler du temps perdu à les créer. Bien sûr, vous devez toujours créer des talons en béton, à utiliser dans de nombreux tests.

La mise en œuvre efficace de Fakes (types Shims, Mocks et Stub) demande un peu d’habitude, mais elle en vaut la peine. J'ai personnellement économisé des semaines de temps de développement grâce à l'utilisation des types Shims/Mole, Mock et Stub. J'espère que vous aurez autant de plaisir avec la technologie que moi!

23
Mike Christian

Si je comprends bien, l’équipe de Visual Studio a voulu éviter de rivaliser avec les diverses bibliothèques factices disponibles pour .NET. MS est souvent confronté à des décisions difficiles comme celle-ci. Ils sont condamnés s’ils ne fournissent pas certaines fonctionnalités ("Pourquoi MS ne nous fournit-il pas une bibliothèque fictive? Les simulacres sont-ils une exigence si courante?") Et damnés s’ils le font ("Pourquoi Microsoft agit-il de manière aussi agressive? des soutiens naturels hors du marché? ") Très souvent, mais pas toujours, ils décident de ne pas simplement proposer leur propre alternative aux technologies disponibles et bien reçues. Cela semble être le cas ici.

La fonctionnalité shim de Fakes est vraiment très utile. Bien sûr, il y a des dangers. Il faut une certaine discipline pour s'assurer que vous ne l'utilisez que lorsque cela est nécessaire. Cependant, cela comble un grand vide. Mon principal grief est qu'il est uniquement livré avec l'édition Ultimate de VS 2012 et qu'il ne sera donc disponible que pour une sous-section de la communauté de développement .NET. Quel dommage.

15
Charles Young

Fakes comprend deux types d'objets "faux". Le premier, appelé "stub", est essentiellement un mannequin généré automatiquement, dont le comportement par défaut peut (et devrait normalement) être remplacé pour en faire une maquette plus intéressante. Cependant, il manque certaines des fonctionnalités offertes par la plupart des frameworks moqueurs actuellement disponibles. Par exemple, si vous souhaitez vérifier qu'une méthode sur une instance de stub a été appelée, vous devez ajouter la logique vous-même. Fondamentalement, si vous créez vos propres simulacres manuellement maintenant, les talons semblent probablement être une amélioration. Toutefois, si vous utilisez déjà un cadre moqueur plus complet, vous aurez peut-être l’impression que certaines pièces importantes manquent dans les talons Fakes.

L’autre catégorie d’objets proposée par Fakes, appelée "cale", expose un mécanisme permettant de remplacer le comportement des dépendances qui n’ont pas été (ou ne peuvent pas) être correctement découplées pour un remplacement standard via des simulacres. À ma connaissance, TypeMock est le seul des principaux frameworks moqueurs offrant actuellement ce type de fonctionnalité.

En passant, si vous avez déjà essayé Moles, Fakes est essentiellement la même chose, sortant finalement de Microsoft Research pour devenir un produit réel.

13
Nicole Calinoiu

En ce qui concerne les objets Fake (Shim + Stub), cela a été bien défini ci-dessus, bien que je suppose que le dernier paragraphe du dernier commentaire résume assez bien la situation.

Bien que beaucoup de gens prétendent que les objets Fake (Shim + Stub) sont de bons atouts dans certains cas de tests unitaires, l'inconvénient est que, que vous utilisiez Visual Studio 2012 ou Visual Studio 2013, ces options sont UNIQUEMENT disponibles. avec les versions Premium ou Ultimate. IOW, cela signifie que vous ne pourrez exécuter aucun de ces Fakes (Shim + Stub) sur une version Pro quelconque.

Vous pouvez probablement voir l'option de menu Fakes (Shim + Stub) sur les versions Pro, mais attention, il y a de fortes chances que vous n'ayez absolument rien ... Cela ne générera aucune erreur de compilation vous indiquant que quelque chose d'important est manquant, les options ne sont tout simplement pas là, alors ne perdez pas votre temps ...

C'est un facteur important à prendre en compte dans une équipe de développement, en particulier si l'une d'entre elles utilise la version Ultimate alors que tout le monde utilise la version Pro ... Moq peut en revanche être facilement installé via Nuget, quelle que soit la version de Visual Studio utilisée. Je n'ai eu aucun problème à utiliser Moq, la clé de tout outil est de savoir à quoi ils servent et comment les utiliser correctement;)

1
SirXamelot