مكتبة لاستئصال التوقعات وإعداد التوقعات على طلبات HTTP في Delphi مع Dunitx.
* تم تطوير WebMocks في Delphi 10.3 (RIO) و 10.4 (سيدني) وحتى الإصدار 3.0 كان متوافقًا مع XE8. نظرًا لأن WebMocks تستخدم مكتبة System.Net التي تم تقديمها مع XE8 ، فلن تكون متوافقة مع الإصدارات السابقة. إذا كنت بحاجة إلى التثبيت على إصدارات Delphi قبل 10.3 ، يجب عليك تثبيت الإصدار 2.0.0.
يتوفر WebMocks 3.2.0 من خلال مدير حزم Embarcadero لـ Delphi Getit. إذا كان لديك إصدار حديث من Delphi بما في ذلك GetIt ، فيجب أن تكون هذه طريقة التثبيت المفضلة.
يجب الآن إدراج أجهزة WebMocks في Delphinus Package Manager.
تأكد من إعادة تشغيل Delphi بعد التثبيت عبر Delphinus وإلا قد لا يمكن العثور على الوحدات في مشاريع الاختبار الخاصة بك.
Source المستخرج إلى "مسار المكتبة" و "مسار التصفح". إذا كنت ترغب في تقديم مقدمة لطيفة إلى WebMocks for Delphi ، فهناك سلسلة من المقالات المنشورة على Dev بدءًا من اختبار عملاء HTTP في Delphi مع Dunitx و WebMocks.
يحتوي Delphi-Webmocks-Demos على مجموعة من المظاهرات لمرافقة المقالات.
لقد أسقط الإصدار 2 Delphi. مساحة الاسم من جميع الوحدات. أي مشاريع ترقية إلى الإصدار 2 أو الأحدث ستحتاج إلى إسقاط Delphi. بادئة من أي وحدات WebMocks متضمنة.
في ملف وحدة الاختبار الخاصة بك ، هناك حاجة إلى بضع خطوات بسيطة.
WebMock إلى uses الواجهة الخاصة بك.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 على خاصية PORT CONTER الحالية وخاصية BaseURL تحتوي على عنوان URL صالح لجذر الخادم.
أبسط أشكال مطابقة الطلب ونقطة البداية لجميع كعبان الطلبات هو بواسطة طريقة HTTP ومسار المستند. على سبيل المثال ، يتم GET الفعل HTTP إلى جذر الخادم / يتم تحقيقه بواسطة:
WebMock.StubRequest( ' GET ' , ' / ' ); يمكن استخدام استخدام * بطاقات برية واحدة لمطابقة أي طلب. على سبيل المثال ، لمطابقة جميع طلبات POST بغض النظر عن مسار المستند الذي يمكنك استخدامه:
WebMock.StubRequest( ' POST ' , ' * ' );وبالمثل ، لمطابقة أي طريقة HTTP لمسار معين يمكنك استخدامه:
WebMock.StubRequest( ' * ' , ' /path ' ); من الممكن تمامًا أن يكون لديك كل شيء من * و * لكل من طريقة HTTP ومسار المستند.
يمكن مطابقة رؤوس طلب HTTP مثل:
WebMock.StubRequest( ' * ' , ' * ' ).WithHeader( ' Name ' , ' Value ' ); يمكن تحقيق مطابقة الرؤوس المتعددة بطريقتين. الأول هو ببساطة سلسلة من المكالمات 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 بواسطة نموذج البيانات كما هو موضح مع content-type من application/x-www-form-urlencoded . يمكن دمج قيم حقل المطابقة المتعددة. على سبيل المثال:
WebMock.StubRequest( ' * ' , ' * ' )
.WithFormData( ' AField ' , ' A value. ' )
.WithFormData( ' AOtherField ' , ' Another value. ' ); لمطابقة وجود حقل ببساطة ، يمكن تمرير بطاقة Wildcard * للقيمة.
ملاحظة: لا يمكنك مطابقة بيانات النموذج ( WithFormData ) ومحتوى الجسم ( WithBody ) في نفس الوقت. سيؤدي تحديد كلاهما إلى أحدث مكالمة فوق المطابقة السابقة.
يمكن أن يكون مطابقة الطلب عن طريق التعبير المنتظم مفيدًا لاستخلاص الطرق الديناميكية لمورد مريح يتضمن اسم مورد ومعرف مورد غير معروف مثل /resource/999 . مثل هذا الطلب يمكن أن يفسد:
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 بواسطة بيانات JSON كما هو موضح مع content-type من application/json باستخدام WithJSON . يمكن دمج قيم حقل المطابقة المتعددة. على سبيل المثال:
WebMock.StubRequest( ' * ' , ' * ' )
.WithJSON( ' ABoolean ' , True)
.WithJSON( ' AFloat ' , 0.123 )
.WithJSON( ' AInteger ' , 1 )
.WithJSON( ' AString ' , ' value ' ); الحجة الأولى يمكن أن تكون طريق. على سبيل المثال ، في JSON التالي ، سوف تتطابق كائنات المسار [ value 1 objects[0].key .
{
"objects" : [
{ "key" : " value 1 " },
{ "key" : " value 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 >يمكن أن تكون الوسيطة الثانية هي قيمة منطقية أو عائمة أو عدد صحيح أو سلسلة.
إذا كانت المطابقة مطلوبة لتكون أكثر تعقيدًا من المطابقة البسيطة ، فيمكن توفير وظيفة مسند في الاختبار للسماح بالتفتيش/المنطق المخصص لمطابقة الطلب. ستتلقى وظيفة المسند المجهول كائن 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 ' );إذا كنت ترغب في إرجاع نوع محتوى معين ، فيمكن تحديده كوسيطة ثانية على سبيل المثال
WebMock.StubRequest( ' GET ' , ' / ' )
.ToRespond.WithBody( ' { "status": "ok" } ' , ' application/json ' ); عند الاستجابات مع المحتوى الثنائي أو الكبير ، من المحتمل أن يكون من الأسهل توفير المحتوى كملف. يمكن تحقيق ذلك باستخدام WithBodyFile الذي له نفس التوقيع كما هو الحال WithBody ولكن الوسيطة الأولى هي المسار إلى ملف.
WebMock.StubRequest( ' GET ' , ' / ' ).WithBodyFile( ' image.jpg ' ); ستحاول Delphi-Webmocks تعيين نوع المحتوى وفقًا لتمديد الملف. إذا كان نوع الملف غير معروف ، فسيقوم نوع المحتوى افتراضيًا application/octet-stream . يمكن تجاوز نوع المحتوى مع الوسيطة الثانية. على سبيل المثال
WebMock.StubRequest( ' GET ' , ' / ' ).WithBodyFile( ' file.myext ' , ' application/xml ' ); ملاحظة: سيكون أحد "Gotcha" للوصول إلى الملفات في الاختبارات هو موقع الملف بالنسبة إلى الاختبار القابل للتنفيذ والذي ، افتراضيًا ، باستخدام برنامج التحويل البرمجي 32 بت سيتم إخراجه إلى مجلد Win32Debug . للرجوع بشكل صحيح ملف اسمه 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 أو Reset على مثيل TwebMock. ستعود طريقة Reset عامة إلى مثيل Twebmock إلى حالة فارغة بما في ذلك إفراغ سجل Stub. سوف ResetStubRegistry الأكثر تحديدًا كما هو مقترح فقط للتسجيل فقط في سجل العنيفة.
يتم تسجيل كل طلب تم تقديمه من مثيل Twebmock في خاصية History . تحتوي إدخالات السجل على جميع معلومات طلب الويب الرئيسية: الطريقة ؛ طلب ؛ الرؤوس والجسم.
من الممكن كتابة التأكيدات بناءً على تاريخ الطلب على سبيل المثال:
WebClient.Get(WebMock.URLFor( ' document ' ));
Assert.AreEqual( ' GET ' , WebMock.History.Last.Method);
Assert.AreEqual( ' /document ' , WebMock.History.Last.RequestURI);ملاحظة: إذا وجدت نفسك تكتب تأكيدات في هذا القصر ، يجب عليك إلقاء نظرة على تأكيدات الطلب التي توفر طريقة أكثر إيجازًا لتحديد هذه التأكيدات.
إذا كنت بحاجة إلى مسح السجل ، فيمكنك استدعاء ResetHistory أو Reset على مثيل Twebmock. ستعيد طريقة 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 . هذا مفيد للتحقق من الكود الخاص بك هو عدم إجراء طلبات إضافية غير مرغوب فيها.
يتبع هذا المشروع الإصدار الدلالي.
حقوق الطبع والنشر © 2019-2024 ريتشارد هثرال ريتشارد@appercept.com
يتم توزيع WebMocks بموجب شروط ترخيص Apache (الإصدار 2.0).
انظر الترخيص للحصول على التفاصيل.