2009-07-02 13 views
1

Version mise à jour de la questionEnregistrement de l'interaction sur un point d'inflexion en utilisant un cadre de simulation. Moq

Hi.

Mon entreprise possède quelques bases de code héritées que j'espère tester dès leur migration vers .NET 3.5. J'ai choisi Moq comme mon framework Mocking (je suis tombé amoureux de la syntaxe précise immédiatement).

Un scénario courant, dont je m'attends à voir beaucoup dans le futur, est celui où je vois un objet qui interagit avec d'autres objets.

Je connais les travaux de Michael Feathers et je réussis à identifier les points d'inflexion et à isoler les composants de taille décente. Extraire et remplacer est roi.

Cependant, il y a une caractéristique qui rendrait ma vie beaucoup plus facile.

Imaginez que Component1 interagisse avec Component2. Component2 est une interface de ligne série bizarre à un centre de feu ou quelque chose avec beaucoup d'inspection d'octet, de moulage et de manipulation de pointeur. Je ne souhaite pas comprendre component2 et son interface héritée consommée par Component1 comporte beaucoup de bagages.

Ce que je voudrais faire, est d'extraire l'interface de Component2 consommée par Component1 et faire quelque chose comme ceci:

component1.FireCentral = new Mock<IComponent2> (component2); 

Je crée une maquette normale, mais je suis PASING dans une instance de le réel Component2 en tant qu'argument de constructeur dans l'objet Mock. Il peut sembler que je fais mon test en fonction de Component2, mais je ne prévois pas de garder ce code. Cela fait partie du rituel «placer l'objet sous test».

Maintenant, j'allumerais le système réel (avec un centre de tir physique connecté), puis interagirais avec mon objet. Ce que je voudrais alors, est d'inspecter le mock pour voir un journal de comment component1 a interagi avec component2 (en utilisant le débogueur pour inspecter une collection de chaînes sur le faux). Et, mieux encore, le simulacre pourrait fournir une liste d'attentes (en C#) qui créeraient ce comportement dans un simulacre qui ne dépendrait pas de Component2, que j'utiliserais alors dans mon code de test.

En bref. Utilisation du cadre de simulation pour enregistrer l'interaction afin que je puisse la lire dans mon code de test.

ancienne version de la question

Salut.

En travaillant avec du code hérité et avec beaucoup de classes d'utilitaires, je me demande parfois comment une classe particulière est influencée par son environnement dans un certain nombre de scénarios. Un cas sur lequel je travaillais ce matin impliquait de sous-classer un MemoryStream régulier de sorte qu'il vidait son contenu dans un fichier lorsqu'il atteignait une certaine taille.

// TODO: Remove 
private class MyLimitedMemoryStream : MemoryStream 
{ 
    public override void Write(byte[] buffer, int offset, int count) 
    { 
     if (GetBuffer().Length > 10000000) 
     { 
      System.IO.FileStream file = new FileStream("c:\\foobar.html",FileMode.Create); 
      var internalbuffer = GetBuffer(); 
      file.Write(internalbuffer,0,internalbuffer.Length); 
     } 
     base.Write(buffer, offset, count); 
    }   
} 

(et j'ai utilisé un point d'arrêt ici pour quitter le programme après l'écriture du fichier). Cela a fonctionné, et j'ai trouvé quel contrôle webform (partie Web-> partie Web-> partie Web) rendu incorrectement. Cependant, le flux de mémoire a un tas d'écriture et d'écriture.Puis-je utiliser un cadre de simulation pour obtenir rapidement un aperçu de la manière dont une instance donnée est traitée? Des astuces intelligentes là-bas? Nous utilisons Rhino Mocks. Je vois cela comme un excellent moyen de travailler avec du code hérité. Surtout si les actions enregistrées dans un scénario peuvent facilement être configurées en tant que nouvelles attentes/critères d'acceptation pour ce même scénario reproduits dans un test unitaire.

Chaque contribution est appréciée. Merci pour la lecture.

+0

Avez-vous trouvé quelque chose pour cela depuis 2009? Je le veux pour la JVM. –

+0

Non le type de cadre moqueur qui enveloppe et enregistre le comportement d'une dépendance me échappe toujours. Il pourrait être temps pour un autre regard sérieux autour, cependant. – Tormod

+0

Voici la même question posée pour Java. http://stackoverflow.com/questions/16400897/record-method-calls-in-one-session-for-replaying-in-future-test-sessions L'une des réponses pointe vers une mise en œuvre majeure. https://gist.github.com/dfreeman/5563829 –

Répondre

0

Je ne pense pas que vous pouvez utiliser un cadre de simulation pour obtenir facilement un aperçu de la façon dont une instance particulière est traitée.

Vous pouvez toutefois utiliser le cadre de simulation pour définir la manière dont il doit être traité afin de vérifier qu'il est traité de cette manière. Dans le code hérité, cela nécessite souvent que le code soit testable, par ex. introduction d'interfaces, etc.

Une technique pouvant être utilisée avec un code existant sans avoir besoin de beaucoup de restructuration du code est l'utilisation de coutures de connexion. Vous pouvez en lire plus à ce sujet dans cet article InfoQ: Using Logging Seams for Legacy Code Unit Testing.

Si vous voulez plus de conseils sur la façon de tester le code existant, je recommande le livre Working Effectively with Legacy Code de Michael Feathers.

Espérons que cela aide!

0

Oui, c'est possible. Si vous utilisez un test rigoureux et lancez un test unitaire qui simule le test, le test échouera, vous indiquant quelle méthode inattendue a été appelée.

Est-ce ce que vous cherchez?

+0

Pas exactement. Si le simulacre avait un journal indiquant toutes les interactions qui lui ont été faites, alors c'est ce que je cherchais. Ou, mieux encore, si le simulacre pouvait envelopper l'objet réel et ensuite être inspecté par la suite pour ce qui était fait à l'objet et comment l'objet répondait, alors ce serait ce que je cherchais. – Tormod

+0

Ok. Je ne pense pas que RhinoMocks ou Moq ait quelque chose comme ça intégré. Vous pourriez essayer de chercher dans TypeMock, qui est facilement le cadre factice le plus puissant. –

0

Les cadres Mock n'ont pas été conçus pour ce problème. Je ne vois pas comment vous pouvez faire cela avec Moq ou RhinoMocks. Même le puissant TypeMock peut ne pas être capable de faire ce que vous demandez. Les frameworks Mock n'étaient pas construits pour cela. À la place, utilisez un outil de programmation orienté aspect (AOP) pour tisser des appels d'invocation avant et après la méthode. Cela fera exactement ce que vous voulez: voir toutes les interactions pour un type particulier. Par exemple, dans le cadre PostSharp AOP, vous indiquez simplement des méthodes que vous aimeriez avant et après appelés un appel de méthode sur un autre objet:

public class Component2TracerAttribute : OnMethodBoundaryAspect 
{ 
    public override void OnEntry(MethodExecutionEventArgs eventArgs) 
    { 
    if (eventArgs.Method == somethingOnComponent2) // Pseudo-code 
    { 
     Trace.TraceInformation("Entering {0}.", eventArgs.Method); 
    } 
    } 

    public override void OnExit(MethodExecutionEventArgs eventArgs) 
    { 
     if (eventArgs.Method == somethingOnComponent2) // Pseudo-code 
     { 
     Trace.TraceInformation("Leaving {0}.", eventArgs.Method); 
     } 
    } 
} 

qui se connectera toutes les méthodes qui sont appelées sur le composant 2.

2

Bienvenue sur le petit club des « visionnaires » qui comprennent cette exigence :)

Malheureusement, je vais vous dire, je ne pense pas que cela existe encore pour .NET. Je suis également sûr qu'il n'existe pas pour Java non plus ... comme je l'ai cherché périodiquement pendant quelques années, et même offert une prime en espèces pour cela sur un site pay-for-work, et rien ne se présente (Certains développeurs russes ont proposé de l'implémenter à partir de zéro, mais c'était en dehors de mon budget).

Mais, j'ai créé un Proof Of Concept en PHP pour démontrer l'idée et peut-être d'autres personnes intéressées à développer cela pour d'autres langages (.NET pour vous, Java pour moi).

Voici la preuve de concept PHP:

http://code.google.com/p/php-mock-recorder/

+0

Merci et bienvenue. En effet. Les simulacres devraient reproduire le comportement. Qui est mieux de décrire l'interaction avec un composant que le composant lui-même? Cela rendrait l'effort de cerclage d'un harnais de test sur des objets beaucoup plus simple et réductible. Vous envelopper simplement tout ce avec lequel vous interagissez par défaut. Si l'interaction enregistrée n'a pas de sens à décrire dans un scénario de test, par exemple si l'interaction est inexistante ou trop intense, vous devriez probablement repenser votre choix de limite de dépendance. Une approche plus pragmatique du problème. – Tormod