2009-07-02 4 views
1

Aktualisierte Version der FrageAufnahme der Interaktion an einem Wendepunkt unter Verwendung eines Mocking-Frameworks. Moq

Hallo.

Meine Firma hat ein paar Legacy-Code-Basen, die ich hoffe, sie zu testen, sobald sie auf .NET 3.5 migrieren. Ich habe Moq als mein Mocking Framework ausgewählt (ich habe mich sofort in die knackige Syntax verliebt).

Ein gängiges Szenario, von dem ich in Zukunft viel zu erwarten habe, ist, wo ich ein Objekt sehe, das mit anderen Objekten interagiert.

Ich kenne die Arbeiten von Michael Feathers und ich bin gut darin, Wendepunkte zu identifizieren und anständige Größen zu isolieren. Extrahieren und Überschreiben ist König.

Es gibt jedoch eine Funktion, die mein Leben viel einfacher machen würde.

Stellen Sie sich vor, dass Component1 mit Component2 interagiert. Component2 ist eine seltsame serielle Schnittstelle zu einem zentralen Brandherd oder eine solche mit viel Byte-Inspektion, Casting und Zeigermanipulation. Ich möchte Component2 nicht verstehen, und seine von Component1 konsumierte Legacy-Schnittstelle bringt viel Gepäck mit sich.

Was würde ich tun, ist die Schnittstelle von Component2 von Component1 verbraucht zu extrahieren und dann etwas tun, wie folgt aus:

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

Ich bin eine normale Mock zu schaffen, aber ich bin pasing in einer Instanz die echte Component2 als Konstruktorargument in das Mock-Objekt. Es scheint, als würde ich meinen Test abhängig von Component2 durchführen, aber ich habe nicht vor, diesen Code beizubehalten. Dies ist Teil des Rituals "Place Object under Test".

Jetzt würde ich das reale System (mit einem physischen Feuer zentral verbunden) und dann mit meinem Objekt interagieren.

Was ich dann wünschen würde, ist die Mock zu überprüfen, um ein Protokoll zu sehen, wie component1 mit component2 interagiert (mit dem Debugger einige Sammlung von Zeichenfolgen auf dem Mock zu überprüfen). Und noch besser, der Mock könnte eine Liste von Erwartungen (in C#) liefern, die dieses Verhalten in einem Mock erzeugen würden, der nicht von Component2 abhängt, den ich dann in meinem Testcode verwenden würde.

Kurz gesagt. Verwenden des Mocking-Frameworks, um die Interaktion aufzuzeichnen, sodass ich sie in meinem Testcode wiedergeben kann.

alte Version Frage

Hallo.

Bei der Arbeit mit Legacy-Code und mit vielen Utility-Klassen frage ich mich manchmal, wie eine bestimmte Klasse in einer Reihe von Szenarien von ihrer Umgebung beeinflusst wird. Ein Fall, an dem ich heute Morgen arbeitete, beinhaltete das Unterklassifizieren eines regulären MemoryStream, so dass er seinen Inhalt bei Erreichen einer bestimmten Größe in eine Datei ablegen würde.

// 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); 
    }   
} 

(und ich benutzte einen Haltepunkt hier, um das Programm zu beenden, nachdem die Datei geschrieben wurde). Das hat funktioniert, und ich habe festgestellt, welches Webformular (Webpart -> Webpart -> Webpart) falsch gerendert wird. Allerdings hat memorystream eine Reihe von Schreib- und Schreibzeilen.

Kann ich ein Mocking-Framework verwenden, um schnell einen Überblick darüber zu erhalten, wie auf eine bestimmte Instanz reagiert wird? Irgendwelche Tricks dort? Wir verwenden Rhino Mocks.

Ich sehe dies als eine große Assett in der Arbeit mit Legacy-Code. Insbesondere, wenn aufgezeichnete Aktionen in einem Szenario leicht als neue Erwartungen/Akzeptanzkriterien für dasselbe Szenario in einem Komponententest repliziert werden können.

Jeder Eingang wird geschätzt. Danke fürs Lesen.

+0

Haben Sie etwas für diese seit 2009 finden? Ich will das für die JVM. –

+0

Nein, der Typ des Mock-Frameworks, der das Verhalten einer Abhängigkeit umschließt und aufzeichnet, entgeht mir immer noch. Es könnte Zeit für einen weiteren ernsthaften Blick sein. – Tormod

+0

Hier ist die gleiche Frage für Java gestellt. http://stackoverflow.com/questions/16400897/record-method-calls-in-one-session-for-replaying-in-future-test-sessions Eine der Antworten verweist auf eine Kern-Implementierung. https://gist.github.com/dfreeman/5563829 –

Antwort

0

Ich glaube nicht, dass Sie ein spöttisches Framework verwenden können, um einfach einen Überblick darüber zu bekommen, wie eine bestimmte Instanz behandelt wird.

Sie können jedoch das Mocking-Framework verwenden, um zu definieren, wie darauf reagiert werden soll, um zu verifizieren, dass auf diese Weise gehandelt wird. Im Legacy-Code erfordert dies oft, den Code testbar zu machen, z. Einführung von Schnittstellen etc.

Eine Technik, die mit Legacy-Code ohne große Umstrukturierung des Codes verwendet werden kann, ist die Verwendung Protokollierung Nähte. Sie können mehr darüber in diesem InfoQ-Artikel lesen: Using Logging Seams for Legacy Code Unit Testing.

Wenn Sie weitere Tipps zum Testen von Legacy-Code wünschen, empfehle ich das Buch Working Effectively with Legacy Code von Michael Feathers.

Hoffe, das hilft!

0

Ja, das ist möglich. Wenn Sie einen strengen Mock verwenden und einen Komponententest ausführen, der den Mock ausführt, schlägt der Test fehl und sagt Ihnen, welche unerwartete Methode aufgerufen wurde.

Ist das wonach Sie suchen?

+0

Nicht genau. Wenn der Spott ein Protokoll hatte, in dem alle Interaktionen mit ihm angegeben waren, dann suchte ich danach. Oder, noch besser, wenn der Mock das reale Objekt umhüllen und dann danach untersuchen könnte, was mit dem Objekt gemacht wurde und wie das Objekt reagiert hat, dann wäre das, wonach ich gesucht habe. – Tormod

+0

Ok. Ich denke nicht, dass RhinoMocks oder Moq so etwas eingebaut hat. Sie könnten versuchen, in TypeMock zu schauen, welches das leistungsstärkste Mock-Framework ist. –

0

Mock-Gerüste wurden nicht für dieses Problem entwickelt. Ich sehe nicht, wie Sie das mit Moq oder RhinoMocks machen können. Selbst der mächtige TypeMock ist möglicherweise nicht in der Lage, das zu tun, was du verlangst. Mock-Frameworks wurden dafür nicht gebaut.

Verwenden Sie stattdessen ein Werkzeug für das aspektorientierte Programmieren (AOP), um Aufrufe der Aufrufe vor und nach der Methode zu verknüpfen. Dies wird genau das tun, was Sie wollen: sehen Sie alle Interaktionen für einen bestimmten Typ. Zum Beispiel in der PostSharp AOP Framework Sie einfach Methoden geben Sie vor und nach einem Methodenaufruf auf einem anderen Objekt aufgerufen mögen:

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); 
     } 
    } 
} 

, dass alle Methoden protokollieren, die auf der Komponente 2.

genannt werden
2

Willkommen im kleinen Club der "Visionäre", die diese Anforderung verstehen :)

Leider werde ich Ihnen sagen, ich glaube nicht, dass dies noch für .NET existiert. Ich bin mir auch ziemlich sicher, dass es auch für Java nicht existiert ... da ich seit ein paar Jahren regelmäßig recherchiere, und sogar eine Geldprämie dafür auf einer Pay-for-Work-Website angeboten habe, und nichts ist aufgetaucht (Einige russische Entwickler boten an, sie von Grund auf zu implementieren, aber das war außerhalb meines Budgets).

Aber ich habe einen Proof of Concept in PHP erstellt, um die Idee zu demonstrieren und vielleicht andere Leute dazu zu bringen, dies für andere Sprachen zu entwickeln (.NET für Sie, Java für mich).

Hier ist die PHP-Proof-of-concept:

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

+0

Danke und herzlich willkommen. In der Tat. Spott sollte Verhalten reproduzieren. Wer kann die Interaktion mit einer Komponente besser beschreiben als die Komponente selbst? Dies würde die Anstrengung der Umreifung eines Testkabelbaums an Objekten viel einfacher und reduzierbarer machen. Sie verpacken einfach alles, mit dem Sie interagieren, standardmäßig. Wenn die aufgezeichnete Interaktion in einem Testfall keinen Sinn ergibt, z. B. wenn die Interaktion nicht vorhanden oder viel zu intensiv ist, sollten Sie wahrscheinlich die Wahl der Abhängigkeitsgrenze neu überdenken. Ein Weg pragmatischer Ansatz für das Problem. – Tormod

Verwandte Themen