該函式庫是XMLHttpRequest的模擬,它提供了一個簡單的介面來模擬與XMLHttpRequest互動。它是用於測試的XMLHttpRequest的直接替代品。
該庫實作了XMLHttpRequest接口,並按照 XMLHTTPRequest 規範中指定的方式處理請求和事件,而無需使用實際的網路請求。您可以透過三種方式回應模擬請求:
您可以使用模擬回應方法來模擬回應、上傳進度、錯誤和其他互動。它們會自動處理較低層級的處理,例如發出事件和更改XMLHttpRequest的readystate屬性。
MockXhr請求timeout屬性和請求超時MockXhr生命週期掛鉤MockXhrServer類MockXhrServer設定MockXhr類MockXhr生命週期掛鉤MockXhrRequest類newMockXhr()newServer()XMLHttpRequest特性透過 npm(節點包管理器)
$ npm install mock-xmlhttprequest
import { newServer } from 'mock-xmlhttprequest' ;
import { functionToTest } from '../src/SomethingToTest' ;
// Adapt based on your testing framework. This example uses Mocha and Chai's syntax.
it ( 'should produce a success response' , async ( ) => {
const server = newServer ( {
get : [ '/my/url' , {
// status: 200 is the default
headers : { 'Content-Type' : 'application/json' } ,
body : '{ "message": "Success!" }' ,
} ] ,
} ) ;
try {
// Installs the server's XMLHttpRequest mock in the "global" context.
// After this, "new XMLHttpRequest()" creates a mock request to which the server replies.
server . install ( /* optional context; defaults to globalThis */ ) ;
// Do something that send()s an XMLHttpRequest to '/my/url' and returns a Promise
// that resolves to the parsed JSON response
const result = await functionToTest ( ) ;
assert . equal ( result . message , 'Success!' ) ;
} finally {
// Restore the original XMLHttpRequest
server . remove ( ) ;
}
} ) ; XMLHttpRequest模擬類別是MockXhr 。它公開與XMLHttpRequest相同的接口,並且是使用XMLHttpRequest的測試程式碼的直接替代品。
有兩個選項可以控制MockXhr實例的行為:
XMLHttpRequest生命週期掛鉤。如果您需要在沒有模擬伺服器提供的功能的情況下對請求進行更多控制,請使用此選項。MockXhrServer類別實作模擬伺服器。您使用newServer建立一個MockXhrServer 。 MockXhrServer自動回應MockXhr請求並使編寫測試變得容易。
使用MockXhrServer的測試的基本結構是:
import { newServer } from 'mock-xmlhttprequest' ;
const server = newServer ( /* routes */ ) ;
try {
server . install ( /* optional context; defaults to globalThis */ ) ;
// Test your code that creates XMLHttpRequests
} finally {
// Reverts server.install() at the end of the test.
// Only do this after the test case has finished creating XMLHttpRequests.
server . remove ( ) ;
}有兩種方法可以讓您的程式碼使用MockXhr類別來取代XMLHttpRequest 。這允許MockXhrServer回應請求:
install()將XMLHttpRequest類別全域替換為伺服器的MockXhr類別。在測試案例結束時,呼叫remove()恢復原始狀態。XMLHttpRequest實例的方式,請直接將MockXhr類別與下列MockXhrServer屬性之一結合使用:xhrFactory是創建MockXhr實例的函數。MockXhr是xhrFactory所建立的實例的類別。此程式碼示範了xhrFactory的用法:
import { newServer } from 'mock-xmlhttprequest' ;
const server = newServer ( /* routes */ ) ;
const savedFactory = MyClass . xhrFactory ;
try {
MyClass . xhrFactory = server . xhrFactory ;
// Test code that creates XMLHttpRequests through MyClass.xhrFactory()
} finally {
// Only do this after the test case has finished creating XMLHttpRequests.
MyClass . xhrFactory = savedFactory ;
}路由定義MockXhrServer如何回應MockXhr請求。它們分為三個部分:
當您傳送MockXhr請求時, MockXhrServer會尋找與請求的方法和 URL 相符的第一個路由。然後它使用路由的請求處理程序進行回應。您也可以設定預設請求處理程序。請求處理程序以聲明方式或程式設計方式定義。
預設情況下,如果請求的timeout屬性設定為非零值且MockXhrServer不回應該請求,它最終會逾時。
有兩種方法可以將路由新增到MockXhrServer :
newServer的routes參數。MockXhrServer方法。 MockXhrServer在請求日誌中記錄它收到的所有MockXhr請求。使用它來驗證您的程式碼發送的XMLHttpRequest請求。
MockXhrServer可以自動產生請求(上傳)和回應(下載)進度事件。預設情況下停用此功能。使用progressRate欄位來啟用此功能。
如果您使用Function類型的請求處理程序以程式設計方式回應MockXhr請求,您也可以產生進度事件。
對MockXhr請求的回應是異步的。這再現了真實的XMLHttpRequest請求的工作方式。因此,您很可能需要使用測試框架的非同步測試支援。例如Mocha測試框架的相關文件在這裡。
onSend生命週期鉤子是回應MockXhr請求所必需的。模擬伺服器會自動處理這個問題。另一個選擇是直接使用MockXhr生命週期掛鉤。在這兩種情況下, onSend生命週期掛鉤都會在呼叫XMLHttpRequest.send()執行上下文完成或清除後執行。在內部,該函式庫使用立即解析的Promise來取得空的呼叫堆疊。
MockXhr請求有幾種MockXhr方法和屬性可以回應請求。這些方法允許以下互動:
有關詳細信息,請參閱模擬響應方法部分。
timeout屬性和請求超時預設情況下,如果您在程式碼中設定XMLHttpRequest的timeout屬性, MockXhr請求會在指定的延遲後自動逾時。這會發出timeout事件並取消請求,如規範中所述。
依靠時間的推移來測試程式碼如何處理超時通常會使測試變得脆弱且難以調試。您可以使用setRequestTimeout()以程式方式觸發逾時。
使用以下選項之一停用自動請求逾時:
MockXhrServer上呼叫disableTimeout() 。這會影響它處理的所有MockXhr實例。MockXhr.timeoutEnabled = false 。 MockXhr類別的這個靜態屬性會影響它的每個實例。MockXhr實例上將timeoutEnabled設定為false 。這僅影響該實例。MockXhr生命週期掛鉤這是不使用MockXhrServer的替代使用模式。您可以直接使用MockXhr生命週期掛鉤。這需要更多程式碼,但您可以更好地控制MockXhr請求。
請注意,如果您只需要擴展模擬伺服器,您也可以將MockXhr生命週期掛鉤與MockXhrServer一起使用。
例子:
import { newMockXhr } from 'mock-xmlhttprequest' ;
import { functionToTest } from '../src/SomethingToTest' ;
// Adapt based on your testing framework. This example uses Mocha and Chai's syntax.
it ( 'should produce a success response' , async ( ) => {
// Get a "local" MockXhr subclass
const MockXhr = newMockXhr ( ) ;
// Mock JSON response
MockXhr . onSend = ( request ) => {
const responseHeaders = { 'Content-Type' : 'application/json' } ;
const response = '{ "message": "Success!" }' ;
request . respond ( 200 , responseHeaders , response ) ;
} ;
try {
// Install in the global context so "new XMLHttpRequest()" creates MockXhr instances
global . XMLHttpRequest = MockXhr ;
// Do something that send()s an XMLHttpRequest to '/my/url' and returns a Promise
// that resolves to the parsed JSON response
const result = await functionToTest ( ) ;
assert . equal ( result . message , 'Success!' ) ;
} finally {
// Restore the original XMLHttpRequest
delete global . XMLHttpRequest ;
}
} ) ; MockXhrServer類此類是一個模擬伺服器,它根據 URL 和方法回應MockXhr請求。
MockXhrServer設定MockXhrServer(routes)論點:
routes :具有伺服器初始路由集的物件。 (選修的)在大多數情況下,您應該使用newServer而不是直接使用此建構函式。
routes物件的鍵是 HTTP 方法。這些值是具有兩個元素的陣列: [url_matcher, request_handler] 。
另請參閱請求 URL 匹配器和請求處理程序。
例子:
const handlerFn = ( request ) => { request . respond ( ) ; } ;
newServer ( {
get : [ '/get' , { status : 200 } ] ,
'my-method' : [ '/my-method' , { status : 201 } ] ,
post : [ '/post' , [ handlerFn , { status : 404 } ] ] ,
} ) ; install(context = globalThis)論點:
context :如果您提供一個值,則install方法會在此上下文(而不是全域上下文)中設定XMLHttpRequest屬性。 (選修的)在全域上下文中安裝伺服器的MockXhr模擬以取代XMLHttpRequest類別。使用remove() 恢復。
remove()恢復由 install() 所做的變更。測試後呼叫此方法。
progressRate如果將progressRate設定為大於0的number ,伺服器會自動產生請求(上傳)和回應(下載)進度事件。每個進度事件都以progressRate位元組遞增。
progressRate僅適用於object類型的請求處理程序。
disableTimeout()和enableTimeout()這些方法會停用或啟用MockXhr的timeout屬性的效果。請參閱“ timeout屬性和請求逾時”。
路由配置伺服器如何回應MockXhr請求。以下分別介紹它們的三個部分。
路線概念鬆散地基於 Express 框架。
允許任何具有有效 HTTP 請求方法的string 。有效方法包括標準方法,例如GET 、 POST 、 PUT和DELETE ,以及其他方法名稱。標準方法名稱不區分大小寫。
請求 URL 匹配器可以是以下類型之一:
string (例如'/my-url' )。RegExp 。true的Function 。此函數接收 URL 作為參數。 請求處理程序可以是以下類型之一:
具有響應屬性的object 。預設值為:
{ status: 200, headers: {}, body: null, statusText: 'OK' }
直接呼叫模擬響應方法的Function 。此函數接收MockXhrRequest實例作為參數。
值為'error'或'timeout'的string 。這將分別觸發錯誤或超時。
上述其他請求處理程序類型的陣列。第一個請求取得第一個處理程序,第二個請求取得第二個處理程序,依此類推。當陣列中沒有其他處理程序時,將重複使用最後一個處理程序。
對於object請求處理程序,伺服器會自動新增Content-Length回應標頭和回應正文的長度。
所有這些處理程序都是等效的:
const handlerObj = { } ;
const handlerFn = ( request ) => { request . respond ( 200 , { 'Content-Length' : '0' } ) ; } ;
const handlerArray = [ { } ] ; get(urlMatcher, handler)論點:
urlMatcher :請求 URL 匹配器。handler :請求處理程序。新增GET HTTP 方法的路由。
post(urlMatcher, handler)論點:
urlMatcher :請求 URL 匹配器。handler :請求處理程序。新增POST HTTP 方法的路由。
put(urlMatcher, handler)論點:
urlMatcher :請求 URL 匹配器。handler :請求處理程序。新增PUT HTTP 方法的路由。
delete(urlMatcher, handler)論點:
urlMatcher :請求 URL 匹配器。handler :請求處理程序。新增DELETE HTTP 方法的路由。
addHandler(method, urlMatcher, handler)論點:
method :作為string HTTP 方法。urlMatcher :請求 URL 匹配器。handler :請求處理程序。新增method HTTP 方法的路由。
setDefaultHandler(handler)論點:
handler :請求處理程序。為不符合任何路由的請求設定預設請求處理程序。
setDefault404()設定返回 404 回應的預設請求處理程序。
xhrFactory傳回新MockXhr實例的函數。
MockXhr伺服器掛鉤的MockXhr類別。 xhrFactory建立此類別的實例。
getRequestLog()傳回迄今為止伺服器收到的所有請求的陣列。每次呼叫都會傳回一個新數組。每個數組元素都是一個具有以下屬性的物件:
method :HTTP 方法string 。url :URL string 。body :請求正文headers :請求標頭作為物件。標頭名稱為小寫。MockXhr類此類別是XMLHttpRequest的模擬。本節記錄了規範中未包含的方法和屬性。
MockXhr.timeoutEnabled此靜態boolean屬性控制來自類別的所有實例的請求的自動逾時。
timeoutEnabled此boolean屬性控制此MockXhr實例的自動逾時。
getResponseHeadersHash()將所有響應標頭作為物件傳回。標頭名稱為小寫。
MockXhr生命週期掛鉤您可以在以下位置為MockXhr生命週期掛鉤定義回呼方法:
MockXhr類別的靜態屬性。此鉤子適用於MockXhr及其子類別的所有實例。MockXhrServer.MockXhr或newMockXhr()傳回的MockXhr子類別的靜態屬性。該鉤子適用於該類別的所有實例。MockXhr實例的屬性。此鉤子僅適用於此實例。如果您為生命週期事件定義多個掛鉤,則會以上述順序呼叫它們。
您通常應該更喜歡第三個選項,它可以更輕鬆地隔離您的測試案例。
onCreate接收這些參數的回呼方法:
xhr :新的MockXhr實例。使用此生命週期掛鉤在建構MockXhr實例時攔截它們。
當創建MockXhr的實例時,在其建構函數的末尾呼叫。因此,此生命週期掛鉤只能作為靜態屬性使用。
import { MockXhr , newMockXhr } from 'mock-xmlhttprequest' ;
// Called for all instances of MockXhr and all its subclasses
MockXhr . onCreate = ( xhr ) => { /*...*/ } ;
// Called for all instances of this MockXhr subclass
const MockXhrSubclass = newMockXhr ( ) ;
MockXhrSubclass . onCreate = ( xhr ) => { /*...*/ } ; onSend接收這些參數的回呼方法:
request :請求的MockXhrRequest 。xhr : MockXhr實例。使用此生命週期掛鉤透過模擬回應方法來回應請求。
每次調用send()後異步調用。每次調用send()都會產生對onSend的調用,並使用單獨的MockXhrRequest實例。
import { MockXhr , newMockXhr } from 'mock-xmlhttprequest' ;
// Called for all instances of MockXhr and all its subclasses
MockXhr . onSend = ( request ) => { /*...*/ } ;
// Called for all instances of this MockXhr subclass
const MockXhrSubclass = newMockXhr ( ) ;
MockXhrSubclass . onSend = ( request ) => { /*...*/ } ;
// Called for this instance only
const xhr = new MockXhrSubclass ( ) ;
xhr . onSend = ( request ) => { /*...*/ } ;MockXhrRequest類每次呼叫send()都會建立一個MockXhrRequest ,其中包含有關XMLHttpRequest的資訊並提供以程式設計方式回應的方法。
requestHeaders包含請求標頭副本的HeadersContainer 。
method包含請求的 HTTP 方法的string 。
url包含請求 URL 的string 。
body請求的正文。
withCredentials具有請求的withCredentials值的boolean 。
getRequestBodySize()請求正文中的位元組number 。
注意:當body是multipart/form-data編碼的FormData時,這並不完全準確。不考慮標頭、編碼和其他影響非模擬XMLHttpRequest真實body大小的因素。您可以使用此方法取得請求的真實body大小的下限值。這對於模擬上傳進度事件很有用。
這些方法提供了一個程式介面來回應MockXhr請求。
如果對回應方法的呼叫無效,則會拋出Error並"Mock usage error detected"的訊息。
uploadProgress(transmitted)論點:
transmitted :傳輸的位元組number 。觸發請求上傳進度。
僅當請求body不為null且上傳未完成時才能呼叫此方法。
呼叫此方法後,您可以使用任何其他模擬響應方法。
respond(status = 200, headers = {}, body = null, statusText = 'OK')論點:
status :回應HTTP狀態number 。 (選修的)headers :有回應頭的object 。 (選修的)body :響應主體。 (選修的)statusText : string回應 HTTP 狀態文字。 (選修的)設定回應標頭和正文的完整回應方法。將請求的readyState更改為DONE 。
觸發適當的事件,例如readystatechange 、 progress和load 。
這是setResponseHeaders()後面跟著setResponseBody()的簡寫。
呼叫此方法後,您將無法使用其他模擬回應方法。如果您再次呼叫open()則此限制將被解除。
setResponseHeaders(status = 200, headers = {}, statusText = 'OK')論點:
status :回應HTTP狀態number 。 (選修的)headers :有回應頭的object 。 (選修的)statusText : string回應 HTTP 狀態文字。 (選修的)設定響應標頭。將請求的readyState更改為HEADERS_RECEIVED 。
觸發適當的事件,例如readystatechange 、 progress和load 。
呼叫該方法後,您可以使用以下模擬響應方法:
downloadProgress()setResponseBody()setNetworkError()setRequestTimeout() 。 downloadProgress(transmitted, length)論點:
transmitted :傳輸的位元組number 。length :回應中的位元組number 。觸發響應進度事件。如果請求的readyState為HEADERS_RECEIVED ,則將其變更為LOADING 。
您必須在此方法之前呼叫setResponseHeaders() 。
setResponseBody(body = null)論點:
body :響應主體。 (選修的)設定響應正文。將請求的readyState更改為DONE 。
觸發適當的事件,例如readystatechange 、 progress和load 。
如果尚未調用,則調用setResponseHeaders() 。然後,回應標頭僅包含Content-Length ,其值等於回應正文的長度。
呼叫此方法後,您將無法使用其他模擬回應方法。如果您再次呼叫open()則此限制將被解除。
setNetworkError()模擬網路錯誤。將請求的readyState更改為DONE 。
觸發適當的事件,包括error事件。
呼叫此方法後,您將無法使用其他模擬回應方法。如果您再次呼叫open()則此限制將被解除。
setRequestTimeout()模擬請求超時。將請求的readyState更改為DONE 。
觸發適當的事件,包括timeout事件。
如果request屬性等於 0,則會引發錯誤,因為在這種情況下不會發生逾時。
呼叫此方法後,您將無法使用其他模擬回應方法。如果您再次呼叫open()則此限制將被解除。
newMockXhr()傳回一個新的MockXhr子類別。
如果您在每個測試案例中使用MockXhr的不同子類,則更容易確保它們是獨立的。例如,如果您在子類別上設定timeoutEnabled靜態屬性,則它只會影響該子類,而不會影響其他測試案例中建立的其他子類別。由於子類別不會被重複使用,因此不需要恢復對子類別所做的變更的清理程式碼。
newServer(routes)論點:
routes :具有伺服器初始路由集的物件。 (選修的)傳回一個新的MockXhrServer及其自己獨特的MockXhr子類別。請參閱newMockXhr() 。
使用可選的routes參數將路由新增至MockXhrServer 。有關詳細信息,請參閱構造函數。
XMLHttpRequest特性基於 XMLHTTPRequest 規範版本「2022 年 8 月 15 日」。
open() 、 setRequestHeader() 、 send()和abort() 。statusText 、標頭和正文。timeout屬性(可以停用)。MockXhr.setNetworkError() )。MockXhr.setRequestTimeout() )。overrideMimeType()在需要時拋出,但沒有其他效果。responseType :完全支援'' 、 'text'和'json' 。 responseType值對傳遞給setResponseBody()的回應正文沒有影響。responseXml :回應正文不會轉換為文件回應。若要取得文件回應,請將其直接作為setResponseBody()中的回應正文傳遞。responseUrl :重定向後的最終請求 URL 不會自動設定。這可以在請求處理程序中模擬。async在open()中設定為false )。open()中解析請求 URL 並在失敗時拋出SyntaxError 。 歡迎貢獻者!請參閱本指南以了解更多資訊。
麻省理工學院