Dunitxを使用したDelphiでのHTTP要求に対するスタブと予想を設定するためのライブラリ。
* WebMocksは、Delphi 10.3(Rio)と10.4(Sydney)で開発され、バージョン3.0がXE8に互換性があるまで開発されました。 WebMocksがXE8で導入されたSystem.Netライブラリを利用しているため、以前のバージョンと互換性がありません。 10.3より前にDelphiバージョンにインストールする必要がある場合は、バージョン2.0.0をインストールする必要があります。
WebMocks 3.2.0は、Delphi GetitのEmbarcaderoのパッケージマネージャーから入手できます。 GetITを含むDelphiの最近のバージョンがある場合、これは推奨されるインストール方法です。
WebMocksは、Delphinus Package Managerにリストされるようになりました。
Delphinusを介してインストールしたらDelphiを再起動してください。そうしないと、ユニットはテストプロジェクトには見つかりません。
Sourceディレクトリを「ライブラリパス」と「ブラウジングパス」に追加します。 Delphi用のWebMocksの穏やかな紹介をご希望の場合は、DunitxとWebMocksを使用してDelphiのHTTPクライアントのテストから始まるDEVに関する一連の記事が公開されています。
Delphi-Webmocks-Demosには、記事に付随する一連のデモが含まれています。
バージョン2がDelphi.すべてのユニットの名前空間。バージョン2以降にアップグレードするプロジェクトは、 Delphi.含まれているWebmocksユニットからのプレフィックス。
テストユニットファイルには、いくつかの簡単な手順が必要です。
usesにWebMockを追加します。TestFixtureクラスでは、 SetupとTearDownを使用して、 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 .デフォルトでは、 TWebMock 8080で動的に割り当てられたポートにバインドされます。この動作は、作成時にポートを指定することでオーバーライドできます。
WebMock := TWebMock.Create( 8088 );テスト内でWebMock.URLFor関数を使用することは、有効なURLの構築を簡素化することです。 Portプロパティには現在のバウンドポートが含まれており、 BaseURLプロパティにはサーバールートの有効なURLが含まれています。
すべての要求スタブのリクエストマッチングと開始点の最も単純な形式は、HTTPメソッドとドキュメントパスです。たとえば、http動詞をGETするため、サーバー/に到達します。
WebMock.StubRequest( ' GET ' , ' / ' );単一のワイルドカード文字*の使用は、任意の要求に合わせて使用できます。たとえば、ドキュメントパスに関係なくすべてのPOSTリクエストを一致させるには、以下を使用できます。
WebMock.StubRequest( ' POST ' , ' * ' );同様に、特定のパスのHTTPメソッドを一致させるには、次のことができます。
WebMock.StubRequest( ' * ' , ' /path ' ); HTTPメソッドとドキュメントパスの両方に対して、 *および*のキャッチオールを持つことが完全に可能です。
HTTPリクエストヘッダーは次のように一致させることができます。
WebMock.StubRequest( ' * ' , ' * ' ).WithHeader( ' Name ' , ' Value ' );複数のヘッダーを一致させることは、2つの方法で実現できます。 1つ目は、単にWithHeaderコールを使用してチェーンすることです。
WebMock.StubRequest( ' * ' , ' * ' )
.WithHeader( ' Header-1 ' , ' Value-1 ' )
.WithHeader( ' Header-2 ' , ' Value-2 ' );あるいは、 WithHeaders 、キー価値のペアのTStringListを受け入れます。
var
Headers: TStringList;
begin
Headers := TStringList.Create;
Headers.Values[ ' Header-1 ' ] := ' Value-1 ' ;
Headers.Values[ ' Header-2 ' ] := ' Value-2 ' ;
WebMock.StubRequest( ' * ' , ' * ' ).WithHeaders(Headers);
end ;HTTPリクエストは、次のようなコンテンツで一致させることができます。
WebMock.StubRequest( ' * ' , ' * ' ).WithBody( ' String content. ' );HTTPリクエストはapplication/x-www-form-urlencodedのcontent-typeで送信されたForm-Dataで一致させることができます。複数の一致するフィールド値を組み合わせることができます。例えば:
WebMock.StubRequest( ' * ' , ' * ' )
.WithFormData( ' AField ' , ' A value. ' )
.WithFormData( ' AOtherField ' , ' Another value. ' );フィールドの存在を単純に一致させるために、値のためにワイルドカード*を渡すことができます。
注:Form-Data( WithFormData )とボディの含有量( WithBody )を同時に一致させることはできません。両方を指定すると、最新の呼び出しが前のマッチャーを上書きします。
定期的な発現によるリクエストを一致させることは/resource/999などのリソース名と未知のリソースIDを含む安らかなリソースの動的ルートをスタブするのに役立ちます。このようなリクエストは、次のように固執する可能性があります。
WebMock.StubRequest( ' GET ' , TRegEx.Create( ' ^/resource/d+$ ' ));一致するヘッダーも同様に、次のことで達成できます。
WebMock.StubRequest( ' * ' , ' * ' )
.WithHeader( ' Accept ' , TRegEx.Create( ' video/.+ ' ));一致するコンテンツは、次のように実行できます。
WebMock.StubRequest( ' * ' , ' * ' )
.WithBody(TRegEx.Create( ' Hello ' ));一致するフォームデータコンテンツは、次のように実行できます。
WebMock.StubRequest( ' * ' , ' * ' )
.WithFormData( ' AField ' , TRegEx.Create( ' .* ' ));注: System.RegularExpressions使用句に追加してください。
HTTP要求は、 WithJSONを使用して、 content-typeのapplication/jsonで送信されたJSONデータと一致させることができます。複数の一致するフィールド値を組み合わせることができます。例えば:
WebMock.StubRequest( ' * ' , ' * ' )
.WithJSON( ' ABoolean ' , True)
.WithJSON( ' AFloat ' , 0.123 )
.WithJSON( ' AInteger ' , 1 )
.WithJSON( ' AString ' , ' value ' );最初の議論はパスになる可能性があります。たとえば、次のJSONでは、パスobjects[0].key value 1と一致します。
{
"objects" : [
{ "key" : " value 1 " },
{ "key" : " value 2 " }
]
}注:文字列パターンは、2番目の引数として正規表現を渡すことで一致させることができます。例えば:
WebMock.StubRequest( ' * ' , ' * ' )
.WithJSON( ' objects[0].key ' , TRegEx.Create( ' valuesd+ ' ));HTTP要求は、送信されたXMLデータ値と一致させることができます。例えば:
WebMock.StubRequest( ' * ' , ' * ' )
.WithXML( ' /Object/Attr1 ' , ' Value 1 ' );最初の議論はXPath式です。前の例では、次のドキュメントに対して前向きな一致します。
<? xml version = " 1.0 " encoding = " UTF-8 " ?>
< Object >
< Attr1 >Value 1</ Attr1 >
</ Object >2番目の引数は、ブール値、フローティングポイント、整数、または文字列値です。
一致するロジックが単純な一致よりも複雑である必要がある場合、リクエストを一致させるためにカスタム検査/ロジックを可能にするために、テストで述語関数を提供できます。匿名の述語関数は、リクエストを検査するためのIWebMockHTTPRequestオブジェクトを受信します。述語関数がTrueを返す場合、スタブは一致と見なされ、 Falseを返すと一致しません。
述語関数を備えたスタブの例:
WebMock.StubRequest(
function(ARequest: IWebMockHTTPRequest): Boolean
begin
Result := True; // Return False to ignore request.
end
);デフォルトでは、応答ステータスは、スタブリクエストに対して200 OKになります。登録されたスタブなしでTWebMockを要求すると、 501 Not Implemented応答します。応答ステータスを指定するには、 ToRespond使用します。
WebMock.StubRequest( ' GET ' , ' / ' ).ToRespond(TWebMockResponseStatus.NotFound);ヘッダーは、次のような応答スタブに追加できます。
WebMock.StubRequest( ' * ' , ' * ' )
.ToRespond.WithHeader( ' Header-1 ' , ' Value-1 ' );リクエストヘッダーと同様に、複数のヘッダーをメソッドチェーンで、または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 ;デフォルトでは、スタブの応答は、コンテンツタイプのtext/plainを備えたゼロ長ボディを返します。 stringとして簡単に表現できる単純な応答コンテンツは、 WithBodyで設定できます。
WebMock.StubRequest( ' GET ' , ' / ' )
.ToRespond.WithBody( ' Text To Return ' );特定のコンテンツタイプを返したい場合は、2番目の引数として指定できます。
WebMock.StubRequest( ' GET ' , ' / ' )
.ToRespond.WithBody( ' { "status": "ok" } ' , ' application/json ' );バイナリまたは大規模なコンテンツを使用して応答する場合、コンテンツをファイルとして提供する方が簡単です。これは、 WithBodyと同じ署名を持つWithBodyFileを使用して実現できますが、最初の引数はファイルへのパスです。
WebMock.StubRequest( ' GET ' , ' / ' ).WithBodyFile( ' image.jpg ' ); Delphi-Webmocksは、ファイル拡張子に従ってコンテンツタイプを設定しようとします。ファイルタイプが不明の場合、コンテンツタイプはデフォルトのapplication/octet-streamになります。コンテンツタイプは、2番目の引数でオーバーライドできます。例えば
WebMock.StubRequest( ' GET ' , ' / ' ).WithBodyFile( ' file.myext ' , ' application/xml ' );注:テストでファイルにアクセスする「Gotcha」の1つは、ファイルの場所がテスト実行可能ファイルに関連していることです。デフォルトでは、Windows 32ビットコンパイラを使用してWin32Debugフォルダーに出力されます。 ProjectフォルダーのContent.txtという名前のファイルを正しく参照するには、パスは....Content.txtになります。
リクエストに動的に応答すると便利な場合があります。例えば:
WebMock.StubRequest( ' * ' , ' * ' )
.ToRespondWith(
procedure ( const ARequest: IWebMockHTTPRequest;
const AResponse: IWebMockResponseBuilder)
begin
AReponse
.WithStatus( 202 )
.WithHeader( ' header-1 ' , ' a-value ' )
.WithBody( ' Some content... ' );
end
);これにより、リクエストのより深い検査を必要とする機能のテストや、応答のリクエストからの値を反映することができます。例えば:
WebMock.StubRequest( ' GET ' , ' /echo_header ' )
.ToRespondWith(
procedure ( const ARequest: IWebMockHTTPRequest;
const AResponse: IWebMockHTTPResponseBuilder)
begin
AResponse.WithHeader( ' my-header ' , ARequest.Headers.Values[ ' my-header ' ]);
end
);また、成功を返す前に、多くの試みのために障害をシミュレートするのに役立ちます。例えば:
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
);現在の登録されたスタブをクリアする必要がある場合は、 ResetStubRegistryを呼び出したり、TwebMockのインスタンスでResetできます。一般的なResetメソッドは、TwebmockインスタンスをStubレジストリを空にするなどの空白状態に返します。より具体的なResetStubRegistry 、提案されているように、スタブレジストリのみを明確にします。
Twebmockインスタンスで行われたすべてのリクエストは、 Historyプロパティに記録されています。履歴エントリには、すべてのキーWebリクエスト情報が含まれています。メソッド。 Requesturi;ヘッダー;と体。
リクエスト履歴に基づいてアサーションを書くことが可能です。
WebClient.Get(WebMock.URLFor( ' document ' ));
Assert.AreEqual( ' GET ' , WebMock.History.Last.Method);
Assert.AreEqual( ' /document ' , WebMock.History.Last.RequestURI);注:このマナーに自分自身が執筆していることに気付いた場合は、これらの主張を定義するためのより簡潔な方法を提供するリクエストアサーションを見てみる必要があります。
リクエスト履歴をクリアする必要がある場合は、TwebMockのインスタンスでResetHistoryに電話するか、 Resetできます。一般的なReset方法は、Twebmockインスタンスを歴史を空にするなどの空白の状態に返します。示唆されているように、より具体的なResetHistory 、歴史のみを明確にします。
Dunitxアサーションを使用して予想通りの動作を検証することに加えて、リクエストアサーションを使用して、リクエストが予想どおりに実行された場合に実行されることをリクエストが期待するかどうかを確認することもできます。
簡単なリクエストアサーション:
WebClient.Get(WebMock.URLFor( ' / ' ));
WebMock.Assert.Get( ' / ' ).WasRequested; // Passesリクエストスタブと同様に、HTTPメソッド、URI、クエリパラメーター、ヘッダー、およびボディコンテンツ( WithJSONおよびWithXMLを含む)でリクエストを一致させることができます。
WebMock.Assert
.Patch( ' /resource`)
.WithQueryParam( ' ParamName ' , ' Value ' )
.WithHeader( ' Content- Type ' , ' application/json ' )
.WithBody( ' { "resource": { "propertyA": "Value" } } ' )
.WasRequested;前向きに主張できるものはすべて( WasRequested )ことも、 WasNotRequested的に主張することができません。これは、コードが余分な不要なリクエストを実行していないことを確認するのに役立ちます。
このプロジェクトは、セマンティックバージョンに従います。
Copyright©2019-2024 Richard Hatherall [email protected]
WebMocksは、Apacheライセンス(バージョン2.0)の条件の下で配布されます。
詳細については、ライセンスを参照してください。