2009-03-04 18 views
3

Gibt es einen Ort oder irgendjemand da draußen, der erklären kann, wie das in einfachem Englisch funktioniert, anstatt "Begriffe in Bezug auf sich selbst zu definieren"?Rhino Mock and Mock allgemein

Antwort

1

Ein Mock ist ein Ersatz, den Sie anweisen können, sich auf eine bestimmte Art und Weise zu verhalten. Dies ist nützlich, um zu testen, wo Sie eine Abhängigkeit beseitigen möchten, indem Sie die tatsächliche Instanz mit einem Scheinobjekt wechseln.

Im Gegensatz zu Stubs behalten Mocks die tatsächliche Verwendung im Auge, sodass Ihr Test möglicherweise bestätigt, dass der Mock wie erwartet verwendet wurde.

Weitere Informationen in Fowlers Artikel here.

9

Sie haben also eine Klasse, die von etwas anderem abhängig ist.

Lets verwenden eine Metapher: ein Auto benötigt einen Motor.

Das Auto ist abhängig vom Motor. Es ist einfach zu testen, dass Auto und Motor zusammen funktionieren, aber was ist mit dem Testen des Autos ohne Motor, oder dass das Auto den Motor korrekt "ruft". Was wir tun könnten, ist etwas (ein Schein) anstelle des Motors, und drücken Sie das Gas (rufen Sie an), und vergewissern Sie sich, dass der falsche (Schein) Motor den richtigen Eingang zum Drosselklappengehäuse erhielt. Anstatt das ganze System zu verifizieren, haben Sie das Ding, das Sie wollen, isoliert getestet, indem Sie mit einem Scheinobjekt gemessen haben.

Es wird viel mehr kompliziert und viel mächtiger in der Praxis, aber ...

3

Wenn Sie Einheiten Test für Ihre Klassen zu schreiben, an einem gewissen Punkt, den Sie in eine Situation kommen werden, wo Ihre Testcode ausführt, einen externen Aufruf Ressource. Meistens ist dies eine Datenbank, aber auch andere sind möglich. Ich benutze normalerweise einen Kreditkartenabrechnungsdienstleister als Beispiel, weil in dieser Situation offensichtlich wird, dass Sie den Dienst nicht jedes Mal aufrufen möchten, wenn Sie einen Test durchführen.

In einer solchen Situation ist es üblich, das Serviceobjekt durch eine Art gefälschten Service zu ersetzen, der keine Ressourcen verwendet. Dies wird als Stub oder Mock-Objekt bezeichnet. Der Unterschied zwischen einem Stich und einem Schein scheint Gegenstand einiger Diskussionen zu sein, aber im Wesentlichen sind sie dieselben.

Spionage-Frameworks wie Rhino Mock helfen Ihnen, Mock-Objekte zu erstellen, die so reagieren, wie Sie es erwarten würden. Sie können die mit den tatsächlichen Antworten der Serviceaufrufe gemachten Aufzeichnungen vergleichen, die Sie bei jeder Durchführung des Tests wiedergeben können.

2

Um wirklich zu verstehen, Mocks Sie zunächst vier Konzepte greifen müssen

Was

Prüfung Interaktion

Was Isolation Frameworks (wie Rhino Mocks)

Was

eine Fälschung ist

Was ist ein Stummel

Und schließlich was ist ein Schein

Beim Interaktionstest wird geprüft, ob eine bestimmte Methode (die Sie gerade testen) eine andere Methode in einer anderen Klasse (die externe Abhängigkeit) mit den Parametern aufruft, die sie verwenden soll. Stellen Sie sich vor, Sie haben eine Methode in einer Klasse, die jedes Mal protokolliert, wenn sie mit ungültigen Parametern aufgerufen wird.Für den Unterschied zwischen Stubs zu klären und verspottet Ich habe 2 externe Abhängigkeiten hinzugefügt (IStringAnalyzer und ILooger):

class SomeClass 
{ 
    IStringAnalyzer stringAnalizer; 
    ILogger logger; 

    public SomeClass(IStringAnalyzer stringAnalyzer, ILogger logger) 
    { 
     this.logger = logger; 
     this.stringAnalyzer = stringAnalyzer; 
    } 


    public void SomeMethod(string someParameter) 
    { 
     if (stringAnalyzer.IsValid(someParameter)) 
     { 
      logger.Log("Invalid string"); 
     }else 
     { 
      //do something with someParameter 
     } 
    } 
} 

In diesem Beispiel, ob ein Methodenaufruf an Someclass Somemethod mit einem ungültigen Parameter testen möchten, ruft das Protokoll Methode in ILogger mit dem String-Parameter "Ungültige Zeichenfolge". Sie nicht wollen Ihre "echten" Implementierungen von IStringAnalyzer und ILogger verwenden, weil diese Fehler haben können, und weil dies Einheit testen Sie nur eine Sache nach der anderen testen möchten, wenn Sie testen, wie mehrere Dinge testen Zu einer Zeit, was Sie wirklich tun, ist Integrationstests. Der Grund dafür, nur eine Sache zu einer Zeit zu testen, ist, dass wenn dein Test fehlschlägt, du sofort weißt, dass es scheitert, weil das einzige, was du testest.

Sie müssen zwei alternative Implementierungen bereitstellen, eine für IStringAnalyzer und eine für ILogger, damit Sie diesen Test ordnungsgemäß durchführen können. Bei diesen alternativen Implementierungen wird es einen Unterschied in Bezug darauf geben, was sie tun müssen. Für IStringAnalyzer möchten Sie nur, dass es, wenn es aufgerufen wird, false zurückgibt, sodass die zu testende Methode den Codepfad durchläuft, den Sie testen möchten. Sie kümmern sich wirklich nicht um den Wert des Parameters (someParameter).

Für ILogger Log-Methode möchten Sie wissen, dass es aufgerufen wurde, und dass es mit "ungültige Zeichenfolge" aufgerufen wurde, so dass Sie dies in Ihrem Test bestätigen können.

Diese beiden alternativen Implementierungen von IStringAnalyzer und ILogger werden beide als "Fälschungen" bezeichnet (weil sie die externen Abhängigkeiten fälschen), aber einer ist ein Stub (IStringAnalyzer) und der andere ist ein Mock (ILogger). Der Stub dient nur dazu, Sie dahin zu bringen, wohin Sie in Ihrem Test gehen müssen (in diesem Fall gibt die IsValid-Methode von IStringAnalyzer false zurück). Der Schein dient dazu, dass Sie überprüfen können, ob die Interaktion mit der externen Abhängigkeit richtig ausgeführt wurde (in diesem Fall ILogger). Einige Leute beziehen sich auf Mocks (oder auf diese Art von Mock) als Test-Spion (meiner Meinung nach ein unendlich besserer Name). Und ja, es gibt andere Arten von Mocks (ich habe sie nie benutzt). Eine gute Quelle dafür ist die Arbeit mit dem Legacy-Code von Michael Feathers und Roy Osheroves The art of unit tests.

Sie können den Stummel und Mock "von Hand", zum Beispiel erstellen:

class StringAnalyzerStub : IStringAnalyzer 
{ 
    public bool whatToReturn; 

    public StubStringAnalyzerStub(bool whatToReturn) 
    { 
     this.whatToReturn = whatToReturn; 
    } 

    public bool IsValid(string parameter) 
    { 
     return whatToReturn; 
    } 
} 


class LoggerMock : ILogger 
{ 
    public string WhatWasPassedIn; 

    public void Log(string message) 
    { 
     WhatWasPassedIn = message; 
    } 
} 

Und hier ist der Test:

[Test] 
public void SomeMethod_InvalidParameter_CallsLogger 
{ 
    IStringAnalyzer s = new StringAnalyzerStub(false); //will always return false when IsValid is called 
    ILogger l = new LoggerMock(); 
    SomeClass someClass = new SomeClass(s, l); 

    someClass.SomeMethod("What you put here doesnt really matter because the stub will always return false"); 

    Assert.AreEqual(l.WhatWasPassedIn, "Invalid string"); 
} 

Die Sache über diese von Hand zu tun ist, dass es Fehler ist anfällig und schwer zu pflegen, daher die Notwendigkeit für die Isolierung Frameworks wie Rhino Mocks. Sie ermöglichen es, diese Mocks und Stubs dynamisch zu erstellen, ist hier, wie der gleiche Test wie mit Rhino Mocks aussehen würde (mit dem arrangieren, zu handeln, behaupten Syntax):

[Test] 
public void SomeMethod_InvalidParameter_CallsLogger 
{ 
    Rhino.Mocks.MockRepository mockRepository = new Rhino.Mocks.MockRepository(); 
    IStringAnalyzer s = mockRepository.Stub<IStringRepository>(); 
    s.Expect(s => s.IsValid("something, doesnt matter").IgnoreParameters().Return(false); 
    ILogger l = mockRepository.DynamicMock<ILogger>(); 
    l.Log("Invalid string"); 
    SomeClass someClass = new SomeClass(s, l); 
    mockRepository.ReplayAll(); 

    someClass.SomeMethod("What you put here doesnt really matter because the stub will always return false"); 

    l.AssertWasCalled(l => l.Log("Invalid string")); 
} 

Keine definierten Begriffe in Bezug auf sich selbst :)

Haftungsausschluss: Ich habe das alles in einem Texteditor geschrieben, daher könnte es einige Syntaxfehler im Code geben ...

Verwandte Themen