Bibliothèque pour les attentes et la définition des attentes sur les demandes HTTP à Delphi avec Dunitx.
* WebMocks a été développé dans Delphi 10.3 (Rio) et 10.4 (Sydney) et jusqu'à ce que la version 3.0 soit compatible à XE8. Comme WebMocks utilise la bibliothèque System.Net introduite avec XE8, elle ne sera pas compatible avec les versions antérieures. Si vous avez besoin d'installation sur les versions Delphi avant 10.3, vous devez installer la version 2.0.0.
WebMocks 3.2.0 est disponible via le gestionnaire de packages d'Embarcadero pour Delphi Getit. Si vous avez une version récente de Delphi, y compris GETIT, cela devrait être la méthode d'installation préférée.
WebMocks devrait désormais être répertorié dans Delphinus Package Manager.
Assurez-vous de redémarrer Delphi après l'installation via Delphinus, sinon les unités ne se trouvent pas dans vos projets de test.
Source extrait au "chemin de la bibliothèque" et "chemin de navigation". Si vous souhaitez une introduction douce à WebMocks pour Delphi, il y a une série d'articles publiés sur Dev commençant par le test des clients HTTP à Delphi avec Dunitx et WebMocks.
Delphi-Webmocks-Demos contient un ensemble de démonstrations pour accompagner les articles.
La version 2 a abandonné le Delphi. Espace de noms de toutes les unités. Tous les projets pas à niveau vers la version 2 ou version ultérieure devront abandonner le Delphi. Préfixe de toutes les unités WebMocks incluses.
Dans votre fichier d'unité de test, quelques étapes simples sont nécessaires.
WebMock aux uses de votre interface.TestFixture , utilisez Setup et TearDown pour créer / détruire une instance de TWebMock . 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 . Par défaut, TWebMock se liera à un port de départ dynamiquement attribué au 8080 . Ce comportement peut être remplacé en spécifiant un port à la création.
WebMock := TWebMock.Create( 8088 ); L'utilisation de la fonction WebMock.URLFor dans vos tests consiste à simplifier la construction d'une URL valide. La propriété Port contient le port lié actuel et la propriété BaseURL contient une URL valide pour la racine du serveur.
La forme la plus simple de la correspondance et le point de départ de la demande pour tous les talons de demande est par la méthode HTTP et le chemin du document. Par exemple, SCHBING Le verbe HTTP GET à la racine du serveur / est réalisé par:
WebMock.StubRequest( ' GET ' , ' / ' ); L'utilisation d'un seul caractère de joker * peut être utilisée pour faire correspondre n'importe quelle demande. Par exemple, pour correspondre à toutes les demandes POST , quel que soit le chemin du document que vous pouvez utiliser:
WebMock.StubRequest( ' POST ' , ' * ' );De même, pour correspondre à n'importe quelle méthode HTTP pour un chemin donné, vous pouvez utiliser:
WebMock.StubRequest( ' * ' , ' /path ' ); Il est parfaitement possible d'avoir un fourre-tout de * et * pour la méthode HTTP et le chemin de document.
Les en-têtes de demande HTTP peuvent être égalés comme:
WebMock.StubRequest( ' * ' , ' * ' ).WithHeader( ' Name ' , ' Value ' ); La correspondance de plusieurs en-têtes peut être réalisée de 2 manières. La première consiste à simplement chaîner avec des appels WithHeader , par exemple:
WebMock.StubRequest( ' * ' , ' * ' )
.WithHeader( ' Header-1 ' , ' Value-1 ' )
.WithHeader( ' Header-2 ' , ' Value-2 ' ); Alternativement, WithHeaders accepte une TStringList de paires de valeurs clés, par exemple:
var
Headers: TStringList;
begin
Headers := TStringList.Create;
Headers.Values[ ' Header-1 ' ] := ' Value-1 ' ;
Headers.Values[ ' Header-2 ' ] := ' Value-2 ' ;
WebMock.StubRequest( ' * ' , ' * ' ).WithHeaders(Headers);
end ;La demande HTTP peut être appariée par du contenu comme:
WebMock.StubRequest( ' * ' , ' * ' ).WithBody( ' String content. ' ); Les demandes HTTP peuvent être appariées par des données de formulaire telles que soumises avec content-type de application/x-www-form-urlencoded . Plusieurs valeurs de champ d'appariement peuvent être combinées. Par exemple:
WebMock.StubRequest( ' * ' , ' * ' )
.WithFormData( ' AField ' , ' A value. ' )
.WithFormData( ' AOtherField ' , ' Another value. ' ); Pour correspondre simplement à la présence d'un champ, un joker * peut être passé pour la valeur.
Remarque: vous ne pouvez pas faire correspondre les données formulaires ( WithFormData ) et le contenu corporel ( WithBody ) en même temps. La spécification des deux se traduira par le dernier appel écrasant le correspondant précédent.
La correspondance d'une demande par l'expression régulière peut être utile pour couper les itinéraires dynamiques pour une ressource reposante impliquant un nom de ressource et un ID de ressource inconnu tel que /resource/999 . Une telle demande pourrait être couchée par:
WebMock.StubRequest( ' GET ' , TRegEx.Create( ' ^/resource/d+$ ' ));Les en-têtes assortis peuvent également réaliser par:
WebMock.StubRequest( ' * ' , ' * ' )
.WithHeader( ' Accept ' , TRegEx.Create( ' video/.+ ' ));Le contenu correspondant peut être effectué comme:
WebMock.StubRequest( ' * ' , ' * ' )
.WithBody(TRegEx.Create( ' Hello ' ));Le contenu des données de forme correspondant peut être effectué comme:
WebMock.StubRequest( ' * ' , ' * ' )
.WithFormData( ' AField ' , TRegEx.Create( ' .* ' )); Remarque: assurez-vous d'ajouter System.RegularExpressions à votre clause Utilisation.
Les demandes HTTP peuvent être appariées par les données JSON telles que soumises avec content-type application/json à l'aide WithJSON . Plusieurs valeurs de champ d'appariement peuvent être combinées. Par exemple:
WebMock.StubRequest( ' * ' , ' * ' )
.WithJSON( ' ABoolean ' , True)
.WithJSON( ' AFloat ' , 0.123 )
.WithJSON( ' AInteger ' , 1 )
.WithJSON( ' AString ' , ' value ' ); Le premier argument peut être un chemin. Par exemple, dans le JSON suivant, les objects[0].key correspondraient à value 1 .
{
"objects" : [
{ "key" : " value 1 " },
{ "key" : " value 2 " }
]
}Remarque: les modèles de chaînes peuvent être appariés en faisant passer une expression régulière comme deuxième argument. Par exemple:
WebMock.StubRequest( ' * ' , ' * ' )
.WithJSON( ' objects[0].key ' , TRegEx.Create( ' valuesd+ ' ));La demande HTTP peut être appariée par les valeurs de données XML soumises. Par exemple:
WebMock.StubRequest( ' * ' , ' * ' )
.WithXML( ' /Object/Attr1 ' , ' Value 1 ' );Le premier argument est une expression XPATH. L'exemple précédent ferait une correspondance positive avec le document suivant:
<? xml version = " 1.0 " encoding = " UTF-8 " ?>
< Object >
< Attr1 >Value 1</ Attr1 >
</ Object >Le deuxième argument peut être un point booléen, un point flottant, un entier ou une valeur de chaîne.
Si la logique de correspondance est nécessaire pour être plus complexe que la correspondance simple, une fonction de prédicat peut être fournie dans le test pour permettre une inspection / logique personnalisée pour la correspondance d'une demande. La fonction de prédicat anonyme recevra un objet IWebMockHTTPRequest pour inspecter la demande. Si la fonction de prédicat renvoie True , le talon sera considéré comme une correspondance, si le rendement False ne sera pas apparié.
Exemple de stub avec fonction de prédicat:
WebMock.StubRequest(
function(ARequest: IWebMockHTTPRequest): Boolean
begin
Result := True; // Return False to ignore request.
end
); Par défaut, un état de réponse sera 200 OK pour une demande Stubbed. Si une demande est faite à TWebMock sans talon enregistré, il répondra 501 Not Implemented . Pour spécifier l'état de la réponse, utilisez ToRespond .
WebMock.StubRequest( ' GET ' , ' / ' ).ToRespond(TWebMockResponseStatus.NotFound);Les en-têtes peuvent être ajoutés à un talon de réponse comme:
WebMock.StubRequest( ' * ' , ' * ' )
.ToRespond.WithHeader( ' Header-1 ' , ' Value-1 ' ); Comme pour l'en-tête de demande, la correspondance de plusieurs en-têtes peut être spécifiée soit via le chaînage de la méthode, soit en utilisant la méthode WithHeaders .
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 ; Par défaut, une réponse Stubbed renvoie un corps de longueur zéro avec text/plain de type contenu. Le contenu de réponse simple qui est facilement représenté en tant que string peut être défini avec WithBody .
WebMock.StubRequest( ' GET ' , ' / ' )
.ToRespond.WithBody( ' Text To Return ' );Si vous souhaitez renvoyer un type de contenu spécifique, il peut être spécifié comme deuxième argument par exemple
WebMock.StubRequest( ' GET ' , ' / ' )
.ToRespond.WithBody( ' { "status": "ok" } ' , ' application/json ' ); Lorsque vous coupez des réponses avec du contenu binaire ou grand, il est probablement plus facile de fournir le contenu en tant que fichier. Cela peut être réalisé en utilisant WithBodyFile qui a la même signature qu'avec WithBody mais le premier argument est le chemin d'accès à un fichier.
WebMock.StubRequest( ' GET ' , ' / ' ).WithBodyFile( ' image.jpg ' ); Les Delphi-Webmocks tenteront de définir le type de contenu en fonction de l'extension de fichier. Si le type de fichier est inconnu, le type de contenu sera par défaut en application/octet-stream . Le type de contenu peut être remplacé par le deuxième argument. par exemple
WebMock.StubRequest( ' GET ' , ' / ' ).WithBodyFile( ' file.myext ' , ' application/xml ' ); Remarque: Un «gotcha» accéder aux fichiers dans les tests est que l'emplacement du fichier sera relatif à l'exécutable de test qui, par défaut, à l'aide du compilateur Windows 32 bits sera sorti dans le dossier Win32Debug . Pour référencer correctement un fichier nommé Content.txt dans le dossier du projet, le chemin sera ....Content.txt .
Parfois, il est utile de répondre dynamiquement à une demande. Par exemple:
WebMock.StubRequest( ' * ' , ' * ' )
.ToRespondWith(
procedure ( const ARequest: IWebMockHTTPRequest;
const AResponse: IWebMockResponseBuilder)
begin
AReponse
.WithStatus( 202 )
.WithHeader( ' header-1 ' , ' a-value ' )
.WithBody( ' Some content... ' );
end
);Cela permet de tester des fonctionnalités qui nécessitent une inspection plus approfondie de la demande ou de refléter les valeurs de la demande dans la réponse. Par exemple:
WebMock.StubRequest( ' GET ' , ' /echo_header ' )
.ToRespondWith(
procedure ( const ARequest: IWebMockHTTPRequest;
const AResponse: IWebMockHTTPResponseBuilder)
begin
AResponse.WithHeader( ' my-header ' , ARequest.Headers.Values[ ' my-header ' ]);
end
);Il peut également être utile pour simuler des échecs pour un certain nombre de tentatives avant de renvoyer un succès. Par exemple:
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
); Si vous devez effacer les talons enregistrés actuels, vous pouvez appeler ResetStubRegistry ou Reset sur l'instance de Twebmock. La méthode Reset générale renverra l'instance TwebMock à un état vierge, y compris la vidange du registre Stume. La ResetStubRegistry plus spécifique sera comme suggéré, effacer uniquement le registre Stub.
Chaque demande faite de l'instance Twebmock est enregistrée dans la propriété History . Les entrées d'historique contiennent toutes les informations de demande Web clé: Méthode; RequestUri; Les en-têtes; et le corps.
Il est possible d'écrire des affirmations basées sur l'historique de la demande, par exemple:
WebClient.Get(WebMock.URLFor( ' document ' ));
Assert.AreEqual( ' GET ' , WebMock.History.Last.Method);
Assert.AreEqual( ' /document ' , WebMock.History.Last.RequestURI);Remarque: Si vous vous retrouvez à rédiger des affirmations dans ce manoir, vous devez jeter un œil aux affirmations de demande qui fournit un moyen plus concis de définir ces affirmations.
Si vous devez effacer l'historique de la demande, vous pouvez appeler ResetHistory ou Reset sur l'instance de Twebmock. La méthode Reset générale renverra l'instance TwebMock à un état vide, y compris la vidange de l'historique. La ResetHistory plus spécifique sera comme suggéré ne perd que l'histoire.
En plus d'utiliser des assertions Dunitx pour valider votre code, vous pouvez également utiliser les assertions de demande pour vérifier si les demandes que vous attendez de votre code fonctionnent là où exécutée comme prévu.
Une simple affirmation de demande:
WebClient.Get(WebMock.URLFor( ' / ' ));
WebMock.Assert.Get( ' / ' ).WasRequested; // Passes Comme pour le coup de demande, vous pouvez faire correspondre les demandes par méthode HTTP, URI, paramètres de requête, en-têtes et contenu corporel (y compris WithJSON et WithXML ).
WebMock.Assert
.Patch( ' /resource`)
.WithQueryParam( ' ParamName ' , ' Value ' )
.WithHeader( ' Content- Type ' , ' application/json ' )
.WithBody( ' { "resource": { "propertyA": "Value" } } ' )
.WasRequested; Tout ce qui peut être affirmé positivement ( WasRequested ) peut également être affirmé négativement avec WasNotRequested . Ceci est utile pour vérifier que votre code n'exécute pas de demandes indésirables supplémentaires.
Ce projet suit le versioning sémantique.
Copyright © 2019-2024 Richard Hatherall [email protected]
WebMocks est distribué selon les termes de la licence Apache (version 2.0).
Voir la licence pour plus de détails.