Votre question portait sur la façon dont le cadre MS Fakes est différent de NMock et il semble que les autres réponses ont résolu certains de ces problèmes, mais voici quelques informations supplémentaires sur la manière dont ils sont identiques et sur la manière dont ils sont différents. NMock est également similaire à RhinoMocks et Moq, je les regroupe donc avec NMock.
Il y a 3 différences majeures que je vois d'emblée entre NMock / RhinoMocks / Moq et le MS Fakes Framework:
Le framework MS fakes utilise du code généré, un peu comme les accesseurs dans les versions précédentes de Visual Studio au lieu de types génériques. Lorsque vous souhaitez utiliser le faux framework pour une dépendance, vous ajoutez l'assembly qui contient la dépendance aux références du projet de test, puis cliquez dessus avec le bouton droit de la souris pour générer les doubles de test (stubs ou shims). Ensuite, lorsque vous testez, vous utilisez en fait ces classes générées à la place. NMock utilise des génériques pour accomplir la même chose (ie IStudentRepository studentRepository = mocks.NewMock<IStudentRepository>()
). À mon avis, l'approche du cadre MS Fakes inhibe la navigation dans le code et la refactorisation à partir des tests puisque vous travaillez en fait contre une classe générée, pas votre véritable interface.
Le cadre de faux MS fournit des talons et des taupes (cales), tandis que NMock, RhinoMocks et Moq fournissent tous des talons et des mocks . Je ne comprends vraiment pas la décision de MS de ne pas inclure de simulacres et je ne suis personnellement pas fan 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 stub. Dans ces autres implémentations, vous pouvez spécifier les valeurs de retour et suivre les informations sur la façon ou si la méthode a été appelée. Avec NMock, RhinoMocks et Moq, vous générez un objet fictif, puis utilisez cet objet 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 des faux MS plus complexe et moins expressive.
Pour clarifier la différence dans ce que fournissent les frameworks: NMock, RhinoMocks et Moq fournissent tous deux types de tests doubles (stubs et mocks). Le faux framework fournit des talons et des taupes (ils les appellent des cales) et n'inclut malheureusement pas les simulacres. 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 doubles de test:
Stubs: Les stubs sont utilisés lorsque vous devez fournir des valeurs pour des méthodes ou des propriétés qui seront demandées à vos doubles de test par la méthode testée. Par exemple, lorsque ma méthode sous test appelle la méthode DoesStudentExist () du test double IStudentRepository, je veux qu'elle renvoie true.
L'idée des stubs dans les faux NMock et MS 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 ceci:
IStudentRepository studentRepository = new DataAccess.Fakes.StubIStudentRepository() // Generated by Fakes.
{
DoesStudentExistInt32 = (studentId) => { return new Student(); }
};
Remarquez dans l'exemple MS Fakes que vous créez une implémentation entièrement nouvelle pour la méthode DoesStudentExist (notez qu'elle s'appelle DoesStudentExistInt32 car le faux framework ajoute les types de données de paramètre aux noms de méthode lorsqu'il génère les objets stub, je pense que cela obscurcit la clarté de les tests). Pour être honnête, l'implémentation NMock me dérange é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 inhibe vraiment le refactoring et je recommande vivement RhinoMocks ou Moq sur 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 faites cela en définissant des attentes similaires à ceci:
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 l'ancien style d'attente alors que RhinoMocks et Moq prennent tous deux en charge l'approche Arrange / Act / Assert où vous spécifiez les interactions attendues sous forme d'assertions à 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 du tout de simulations. Cela signifie que dans vos implémentations stubbed (voir la description des stubs ci-dessus), vous devez définir des variables que vous vérifierez plus tard qu'elles étaient correctement définies. Cela ressemblerait à quelque chose comme ceci:
bool wasFindCalled = false;
IStudentRepository studentRepository = new DataAccess.Fakes.StubIStudentRepository()
{
DoesStudentExistInt32 = (studentId) =>
{
wasFindCalled = true;
return new Student();
}
};
classUnderTest.MethodUnderTest();
Assert.IsTrue(wasFindCalled);
Je trouve que cette approche est un peu compliquée car vous devez suivre l'appel dans le talon, puis l'affirmer plus tard dans le test. Je trouve que les exemples NMock, et en particulier les RhinoMocks, sont plus expressifs.
Moles (Shims): Pour être franc, je n'aime pas les grains de beauté, en raison de leur potentiel d'abus. Une des choses que j'aime tant dans les tests unitaires (et TDD en particulier) est que tester votre code vous aide à comprendre où vous avez écrit un code médiocre. En effet, il est difficile de tester un code mal écrit. Ce n'est pas le cas lors de l'utilisation de moles, car les moles sont en fait conçues pour vous permettre de tester des dépendances qui ne sont pas 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 celui-ci:
using (ShimsContext.Create())
{
System.Fakes.ShimDateTime.NowGet = () => { return new DateTime(fixedYear, 1, 1); };
}
Mon souci avec les shims est que les gens commenceront à les voir comme "un moyen plus simple de tester les unités" car cela ne vous oblige pas à écrire du code comme vous le devriez. Pour un article plus complet sur ce concept, consultez mon article:
Pour plus d'informations sur certaines préoccupations liées aux faux frameworks, consultez ces articles:
Si vous êtes intéressé à apprendre RhinoMocks, voici une vidéo de formation Pluralsight (divulgation complète - j'ai écrit ce cours et je reçois des redevances payées pour les vues, mais je pense que cela s'applique à cette discussion, je l'inclus ici):
Vous avez raison, mais il y a plus dans l'histoire. Les choses les plus importantes à retenir de cette réponse sont:
Votre architecture doit utiliser correctement les stubs et l'injection de dépendances, plutôt que de compter sur la béquille de faux et de simulations
Les faux et les simulacres sont utiles pour tester le code que vous ne devriez pas ou ne pouvez pas changer, comme:
Shims (connu sous le nom de "Moles", lors du développement) est en effet un cadre moqueur qui fonctionne par des appels détournés. Au lieu de construire minutieusement une maquette (oui, même l'utilisation de Moq est relativement pénible!), Les shims utilisent simplement l'objet de code de production déjà en place. Les shims réacheminent simplement l'appel de la cible de production vers le délégué de test.
Les 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 de perdre du temps à les créer. Bien sûr, vous devez toujours créer des stubs concrets, à utiliser dans de nombreux tests.
La mise en œuvre efficace de Fakes (types Shims, Mocks et Stub) prend un peu de temps pour s'y habituer, mais cela en vaut la peine. J'ai personnellement économisé des semaines de temps de développement, grâce à l'utilisation des types Shims / Mole, Mocks et Stub. J'espère que vous vous amuserez autant que moi avec la technologie!
la source
Si je comprends bien, l'équipe de Visual Studio a voulu éviter de concurrencer les diverses bibliothèques simulées disponibles pour .NET. La SP est souvent confrontée à des décisions difficiles comme celle-ci. Ils sont bloqués s'ils ne fournissent pas certaines fonctionnalités ("pourquoi MS ne nous fournit-il pas une fausse bibliothèque; les simulations sont une exigence si courante?") Et damnés s'ils le font ("pourquoi Microsoft agit-il si agressivement et partisans naturels du marché? ") Très souvent, mais pas toujours, ils décident de ne pas simplement fournir leur propre alternative aux technologies disponibles et bien accueillies. Cela semble être le cas ici.
La fonction de cale de Fakes est vraiment, vraiment utile. Bien sûr, il y a des dangers. Il faut une certaine discipline pour s'assurer que vous ne l'utilisez que lorsque c'est nécessaire. Cependant, cela comble un grand vide. Ma principale plainte est qu'il n'est livré qu'avec l'édition Ultimate de VS 2012 et ne sera donc disponible que pour une sous-section de la communauté de développement .NET. Quel dommage.
la source
Fakes comprend deux types différents de "faux" objets. Le premier, appelé "stub", est essentiellement un mannequin auto-généré dont le comportement par défaut peut (et serait généralement) remplacé pour en faire un simulacre plus intéressant. Il manque cependant certaines des fonctionnalités offertes par la plupart des frameworks de simulation actuellement disponibles. Par exemple, si vous voulez vérifier qu'une méthode sur une instance de stub a été appelée, vous devez ajouter vous-même la logique pour cela. Fondamentalement, si vous créez vos propres simulations manuellement maintenant, les stubs sembleraient probablement une amélioration. Cependant, si vous utilisez déjà un cadre de simulation plus complet, vous pourriez avoir l'impression qu'il manque des pièces importantes dans les faux stubs.
L'autre catégorie d'objet proposée par Fakes, appelée «shim», expose un mécanisme de remplacement du comportement de dépendances qui n'ont pas été (ou ne peuvent pas être) découplées de manière adéquate pour un remplacement standard via des simulacres. AFAIK, TypeMock est le seul des principaux frameworks moqueurs à offrir actuellement ce type de fonctionnalités.
BTW, si vous avez déjà essayé Moles, Fakes est essentiellement la même chose, finissant par sortir de Microsoft Research et devenir un produit réel.
la source
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 dans son ensemble.
Bien que beaucoup de gens soutiennent que les objets Fake (Shim + Stub) sont de bons atouts à avoir dans certains cas de test unitaire, l'inconvénient est que peu importe si vous utilisez Visual Studio 2012 ou Visual Studio 2013, ces options sont UNIQUEMENT disponibles avec les versions Premium ou Ultimate. IOW, cela signifie que vous NE SEREZ AUCUN de ces faux (Shim + Stub) sur aucune version Pro.
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 vous retrouviez avec absolument rien ... Cela ne générera aucune erreur de compilation vous indiquant que quelque chose d'important manque, 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, surtout si l'un est le seul à utiliser la version Ultimate alors que tout le monde utilise la version Pro ... Moq, d'autre part, peut facilement être installé via Nuget, quelle que soit la version de Visual Studio que vous utilisez. 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;)
la source