Bibliothek für Stubbing und Festlegen der Erwartungen an HTTP -Anforderungen in Delphi mit Dunitx.
* Webmocks wurde in Delphi 10.3 (RIO) und 10.4 (Sydney) entwickelt und bis Version 3.0 wieder mit XE8 kompatibel. Da WebMocks die mit XE8 eingeführte System.Net -Bibliothek nutzt, ist sie nicht mit früheren Versionen kompatibel. Wenn Sie vor 10.3 auf Delphi -Versionen installiert werden müssen, sollten Sie Version 2.0.0 installieren.
Webmocks 3.2.0 ist über den Paketmanager von Embarcadero für Delphi GetIt erhältlich. Wenn Sie eine aktuelle Version von Delphi einschließlich Getit haben, sollte dies die bevorzugte Installationsmethode sein.
Webmocks sollten jetzt in Delphinus Paket Manager aufgeführt werden.
Stellen Sie sicher, dass Sie Delphi nach der Installation über Delphinus neu starten. Andernfalls können die Einheiten in Ihren Testprojekten möglicherweise nicht gefunden werden.
Source zum "Bibliothekspfad" und "Browsing Path" hinzu. Wenn Sie eine sanfte Einführung in Webmocks für Delphi möchten, gibt es eine Reihe von Artikeln, die auf Dev veröffentlicht werden, beginnend mit Testen von HTTP -Clients in Delphi mit Dunitx und Webmocks.
Delphi-Webmocks-Demos enthält eine Reihe von Demonstrationen, um die Artikel zu begleiten.
Version 2 hat den Delphi. Namespace aus allen Einheiten. Alle Projekte, die auf Version 2 oder später aktualisieren, müssen den Delphi. Präfix aus allen enthaltenen Webmocks -Einheiten.
In Ihrer Testeinheitsdatei sind einige einfache Schritte erforderlich.
WebMock zu Ihren uses hinzu.TestFixture -Klassen Setup und TearDown um eine Instanz von TWebMock zu erstellen/zu zerstören. unit MyTestObjectTests;
interface
uses
DUnitX.TestFramework,
MyObjectUnit,
WebMock;
type
TMyObjectTests = class (TObject)
private
WebMock: TWebMock;
Subject: TMyObject;
public
[Setup]
procedure Setup ;
[TearDown]
procedure TearDown ;
[Test]
procedure TestGet ;
end ;
implementation
procedure TMyObjectTests.Setup ;
begin
WebMock := TWebMock.Create;
end ;
procedure TMyObjectTests.TearDown ;
begin
WebMock.Free;
end ;
procedure TMyObjectTests.TestGet ;
begin
// Arrange
// Stub the request
WebMock.StubRequest( ' GET ' , ' /endpoint ' );
// Create your subject and point it at the endpoint
Subject := TMyObject.Create;
Subject.EndpointURL := WebMock.URLFor( ' endpoint ' );
// Act
Subject.Get;
// Assert: check your subject behaved correctly
Assert.IsTrue(Subject.ReceivedResponse);
end ;
initialization
TDUnitX.RegisterTestFixture(TMyObjectTests);
end . Standardmäßig binden TWebMock an einen dynamisch zugewiesenen Port bei 8080 . Dieses Verhalten kann durch Angabe eines Ports bei der Erstellung überschrieben werden.
WebMock := TWebMock.Create( 8088 ); Die Verwendung von WebMock.URLFor -Funktion in Ihren Tests besteht darin, die Erstellung einer gültigen URL zu vereinfachen. Die Port -Eigenschaft enthält die aktuelle gebundene Port und BaseURL -Eigenschaft enthält eine gültige URL für das Serverroot.
Die einfachste Form der Anforderungsübereinstimmung und des Ausgangspunkts für alle Anforderungs -Stubs ist die HTTP -Methode und den Dokumentenpfad. Zum Beispiel stubieren das HTTP GET zum Server -Root / wird durch:
WebMock.StubRequest( ' GET ' , ' / ' ); Die Verwendung eines einzelnen Wildcard-Charakters * kann verwendet werden, um eine beliebige Anforderung abzustimmen. Zum Beispiel, um alle POST unabhängig vom Dokumentenpfad zu entsprechen, den Sie verwenden können:
WebMock.StubRequest( ' POST ' , ' * ' );In ähnlicher Weise können Sie jede HTTP -Methode für einen bestimmten Pfad entsprechen, den Sie verwenden können:
WebMock.StubRequest( ' * ' , ' /path ' ); Es ist durchaus möglich, einen Cat-All of * und * für die HTTP-Methode und den Dokumentpfad zu haben.
HTTP -Anfrage -Header können wie:
WebMock.StubRequest( ' * ' , ' * ' ).WithHeader( ' Name ' , ' Value ' ); Übereinstimmende mehrere Header können auf 2 Arten erreicht werden. Die erste besteht darin, einfach mit dem Lehea WithHeader z. B. zu ketten:
WebMock.StubRequest( ' * ' , ' * ' )
.WithHeader( ' Header-1 ' , ' Value-1 ' )
.WithHeader( ' Header-2 ' , ' Value-2 ' ); Alternativ akzeptiert WithHeaders eine TStringList von Schlüsselwertpaaren, z. B.:
var
Headers: TStringList;
begin
Headers := TStringList.Create;
Headers.Values[ ' Header-1 ' ] := ' Value-1 ' ;
Headers.Values[ ' Header-2 ' ] := ' Value-2 ' ;
WebMock.StubRequest( ' * ' , ' * ' ).WithHeaders(Headers);
end ;Die HTTP -Anforderung kann mit Inhalten wie folgt übereinstimmen:
WebMock.StubRequest( ' * ' , ' * ' ).WithBody( ' String content. ' ); HTTP-Anfragen können mit Formdaten mit content-type application/x-www-form-urlencoded übereinstimmen. Mehrere Matching -Feldwerte können kombiniert werden. Zum Beispiel:
WebMock.StubRequest( ' * ' , ' * ' )
.WithFormData( ' AField ' , ' A value. ' )
.WithFormData( ' AOtherField ' , ' Another value. ' ); Um einfach der Anwesenheit eines Feldes zu entsprechen, kann eine Wildcard * für den Wert übergeben werden.
HINWEIS: Sie können nicht gleichzeitig die Formdaten ( WithFormData ) und den Körpergehalt ( WithBody ) übereinstimmen. Wenn Sie beide angeben, wird das neueste Anruf überschreiben, das den vorherigen Matcher überschreibt.
Die Übereinstimmung mit einer Anforderung durch reguläre Expression kann nützlich sein, um dynamische Routen für eine erholsame Ressource mit einem Ressourcennamen und einer unbekannten Ressourcen-ID wie /resource/999 zu stützen. Eine solche Anfrage könnte gestoppt werden von:
WebMock.StubRequest( ' GET ' , TRegEx.Create( ' ^/resource/d+$ ' ));Übereinstimmende Header können ähnlich durch erreicht werden durch:
WebMock.StubRequest( ' * ' , ' * ' )
.WithHeader( ' Accept ' , TRegEx.Create( ' video/.+ ' ));Übereinstimmende Inhalte können durchgeführt werden wie:
WebMock.StubRequest( ' * ' , ' * ' )
.WithBody(TRegEx.Create( ' Hello ' ));Übereinstimmende Formdateninhalte können wie:
WebMock.StubRequest( ' * ' , ' * ' )
.WithFormData( ' AField ' , TRegEx.Create( ' .* ' )); HINWEIS: Achten Sie darauf, dass Ihre Verwendungsklausel System.RegularExpressions hinzufügen.
HTTP-Anfragen können mit JSON-Daten übereinstimmen, wie sie mit content-type von application/json mit WithJSON übermittelt werden. Mehrere Matching -Feldwerte können kombiniert werden. Zum Beispiel:
WebMock.StubRequest( ' * ' , ' * ' )
.WithJSON( ' ABoolean ' , True)
.WithJSON( ' AFloat ' , 0.123 )
.WithJSON( ' AInteger ' , 1 )
.WithJSON( ' AString ' , ' value ' ); Das erste Argument kann ein Weg sein. Zum Beispiel würde im folgenden JSON die objects[0].key mit value 1 übereinstimmen.
{
"objects" : [
{ "key" : " value 1 " },
{ "key" : " value 2 " }
]
}HINWEIS: Saitenmuster können durch die Übergabe eines regulären Ausdrucks als zweites Argument übereinstimmen. Zum Beispiel:
WebMock.StubRequest( ' * ' , ' * ' )
.WithJSON( ' objects[0].key ' , TRegEx.Create( ' valuesd+ ' ));Die HTTP -Anforderung kann mit über eingereichten XML -Datenwerten übereinstimmen. Zum Beispiel:
WebMock.StubRequest( ' * ' , ' * ' )
.WithXML( ' /Object/Attr1 ' , ' Value 1 ' );Das erste Argument ist ein XPath -Ausdruck. Das vorherige Beispiel würde das folgende Dokument positiv übereinstimmen:
<? xml version = " 1.0 " encoding = " UTF-8 " ?>
< Object >
< Attr1 >Value 1</ Attr1 >
</ Object >Das zweite Argument kann ein boolescher, schwebender Punkt, eine Ganzzahl oder ein Stringwert sein.
Wenn eine passende Logik komplexer ist als die einfache Übereinstimmung, kann im Test eine Prädikatfunktion bereitgestellt werden, um eine benutzerdefinierte Inspektion/Logik für die Anpassung einer Anforderung zu ermöglichen. Die anonyme Prädikatfunktion erhält ein IWebMockHTTPRequest -Objekt zur Überprüfung der Anfrage. Wenn die Prädikatfunktion True zurückgibt, wird der Stub als Übereinstimmung angesehen, wenn er False zurückgibt, wird er nicht übereinstimmt.
Beispiel Stub mit Prädikatfunktion:
WebMock.StubRequest(
function(ARequest: IWebMockHTTPRequest): Boolean
begin
Result := True; // Return False to ignore request.
end
); Standardmäßig ist ein Antwortstatus 200 OK für eine stumpfe Anfrage. Wenn TWebMock ohne registrierte Stub eine Anfrage gestellt wird, wird 501 Not Implemented . Um den Antwortstatus anzugeben, verwenden Sie ToRespond .
WebMock.StubRequest( ' GET ' , ' / ' ).ToRespond(TWebMockResponseStatus.NotFound);Header können zu einem Antwortstub hinzugefügt werden wie:
WebMock.StubRequest( ' * ' , ' * ' )
.ToRespond.WithHeader( ' Header-1 ' , ' Value-1 ' ); Wie bei den Anforderungen, die mehrere Header entsprechen, können mehrere Header entweder durch Methodenketten oder mithilfe der Methode WithHeaders angegeben werden.
WebMock.StubRequest( ' * ' , ' * ' ).ToRespond
.WithHeader( ' Header-1 ' , ' Value-1 ' )
.WithHeader( ' Header-2 ' , ' Value-2 ' );
/* or */
var
Headers: TStringList;
begin
Headers := TStringList.Create;
Headers.Values[ ' Header-1 ' ] := ' Value-1 ' ;
Headers.Values[ ' Header-2 ' ] := ' Value-2 ' ;
WebMock.StubRequest( ' * ' , ' * ' )
.ToRespond.WithHeaders(Headers);
end ; Standardmäßig gibt eine Stubbed-Antwort eine Null-Länge-Karosserie mit inhaltlichem text/plain zurück. Einfacher Antwortinhalt, der leicht als string dargestellt wird, kann mit WithBody eingestellt werden.
WebMock.StubRequest( ' GET ' , ' / ' )
.ToRespond.WithBody( ' Text To Return ' );Wenn Sie ein bestimmtes Inhalt zurückgeben möchten, kann es als zweites Argument angegeben werden, z.
WebMock.StubRequest( ' GET ' , ' / ' )
.ToRespond.WithBody( ' { "status": "ok" } ' , ' application/json ' ); Wenn Stubbing -Antworten mit binären oder großen Inhalten ist, ist es wahrscheinlich einfacher, den Inhalt als Datei bereitzustellen. Dies kann unter Verwendung von WithBodyFile erreicht werden, die die gleiche Signatur wie WithBody hat, aber das erste Argument ist der Pfad zu einer Datei.
WebMock.StubRequest( ' GET ' , ' / ' ).WithBodyFile( ' image.jpg ' ); Die Delphi-Webmocks versuchen, den Inhaltstyp gemäß der Dateierweiterung festzulegen. Wenn der Dateityp unbekannt ist, wird der Inhaltstyp standardmäßig an application/octet-stream standardmäßig. Der Inhaltstyp kann mit dem zweiten Argument überschrieben werden. z.B
WebMock.StubRequest( ' GET ' , ' / ' ).WithBodyFile( ' file.myext ' , ' application/xml ' ); Hinweis: Ein "gotcha" -Auffertigungsdateien in Tests ist der Speicherort der Datei relativ zum ausführbaren Test, der standardmäßig mit dem Windows 32-Bit-Compiler in den Ordner Win32Debug ausgegeben wird. Um eine Datei namens Content.txt im Projektordner korrekt zu verweisen, ist der Pfad ....Content.txt .
Manchmal ist es nützlich, auf eine Anfrage dynamisch zu reagieren. Zum Beispiel:
WebMock.StubRequest( ' * ' , ' * ' )
.ToRespondWith(
procedure ( const ARequest: IWebMockHTTPRequest;
const AResponse: IWebMockResponseBuilder)
begin
AReponse
.WithStatus( 202 )
.WithHeader( ' header-1 ' , ' a-value ' )
.WithBody( ' Some content... ' );
end
);Dies ermöglicht das Testen von Funktionen, die eine tiefere Überprüfung der Anforderung erfordern oder Werte aus der Anforderung zurück in der Antwort widerspiegeln. Zum Beispiel:
WebMock.StubRequest( ' GET ' , ' /echo_header ' )
.ToRespondWith(
procedure ( const ARequest: IWebMockHTTPRequest;
const AResponse: IWebMockHTTPResponseBuilder)
begin
AResponse.WithHeader( ' my-header ' , ARequest.Headers.Values[ ' my-header ' ]);
end
);Es kann auch nützlich sein, um Misserfolge für eine Reihe von Versuchen zu simulieren, bevor er einen Erfolg zurückgibt. Zum Beispiel:
var LRequestCount := 0 ;
WebMock.StubRequest( ' GET ' , ' /busy_endpoint ' )
.ToRespondWith(
procedure ( const ARequest: IWebMockHTTPRequest;
const AResponse: IWebMockHTTPResponseBuilder)
begin
Inc(LRequestCount);
if LRequestCount < 3 then
AResponse.WithStatus( 408 , ' Request Timeout ' )
else
AResponse.WithStatus( 200 , ' OK ' );
end
); Wenn Sie die aktuellen registrierten Stubs löschen müssen, können Sie ResetStubRegistry aufrufen oder auf der Instanz von Twebmock Reset . Die allgemeine Reset -Methode gibt die TWEBMOCK -Instanz in einen leeren Zustand zurück, einschließlich der Entleerung des Stub -Registers. Die spezifischere ResetStubRegistry wird wie vorgeschlagen nur das Stub -Registry deutlich.
Jede Anfrage aus der Twebmock -Instanz wird in der History des Verlaufs aufgezeichnet. Verlaufseinträge enthalten alle wichtigen Webanfrageninformationen: Methode; Requesturi; Header; und Körper.
Es ist möglich, Behauptungen zu schreiben, die auf dem Anforderungshistorium basieren, z. B.:
WebClient.Get(WebMock.URLFor( ' document ' ));
Assert.AreEqual( ' GET ' , WebMock.History.Last.Method);
Assert.AreEqual( ' /document ' , WebMock.History.Last.RequestURI);Hinweis: Sollten Sie sich in diesem Herrenhausbekämpfung anfordern, sollten Sie einen Blick auf Anforderungsbehauptungen werfen, die eine prägnantere Möglichkeit bieten, diese Behauptungen zu definieren.
Wenn Sie den Anforderungsverlauf löschen müssen, können Sie ResetHistory anrufen oder auf der Instanz von Twebmock Reset . Die allgemeine Reset -Methode gibt die TWEBMOCK -Instanz in einen leeren Zustand zurück, einschließlich der Entleerung der Geschichte. Die spezifischere ResetHistory wird wie vorgeschlagen nur die Geschichte deutlich.
Zusätzlich zur Verwendung von Dunitx -Behauptungen, um Ihren Code wie erwartet zu validieren, können Sie auch Anforderungsbehauptungen verwenden, um zu überprüfen, ob Anforderungen Sie erwarten, dass Ihr Code wie erwartet ausgeführt wird.
Eine einfache Anfrage behauptet:
WebClient.Get(WebMock.URLFor( ' / ' ));
WebMock.Assert.Get( ' / ' ).WasRequested; // Passes Wie bei der Anfrage Stubbing können Sie Anforderungen mit der HTTP -Methode, URI, Abfrageparametern, Header und Körpergehalt (einschließlich WithJSON und WithXML ) übereinstimmen.
WebMock.Assert
.Patch( ' /resource`)
.WithQueryParam( ' ParamName ' , ' Value ' )
.WithHeader( ' Content- Type ' , ' application/json ' )
.WithBody( ' { "resource": { "propertyA": "Value" } } ' )
.WasRequested; Alles, was positiv ( WasRequested ) geltend gemacht werden kann, kann auch negativ mit WasNotRequested geltend gemacht werden. Dies ist nützlich, um zu überprüfen, ob Ihr Code keine extra unerwünschten Anfragen ausführt.
Dieses Projekt folgt der semantischen Versionierung.
Copyright © 2019-2024 Richard Hatherall [email protected]
WebMocks wird unter den Bestimmungen der Apache -Lizenz (Version 2.0) verteilt.
Weitere Informationen finden Sie in Lizenz.